video merge

This commit is contained in:
Peter Maquiran
2024-02-07 16:45:53 +01:00
parent 4c56fa819c
commit 60edd1ca01
11 changed files with 586 additions and 421 deletions
@@ -2,6 +2,17 @@ import { Injectable } from '@angular/core';
import { ok, err, Result } from 'neverthrow';
import { ObjectMergeNotification } from 'src/app/services/socket-connection-mcr.service';
import { CMAPIService } from "src/app/shared/repository/CMAPI/cmapi.service"
const objectMergeNotification = new ObjectMergeNotification()
export enum UploadError {
noConnection = 'noConnection',
slow = 'slow'
}
export type IOUploadError = "noConnection" | "slow"
@Injectable({
providedIn: 'root'
})
@@ -9,112 +20,85 @@ export class UploadStreamingService {
constructor( private CMAPIService: CMAPIService,) { }
}
class UploadFileUseCase {
CMAPIService: CMAPIService = window["CMAPIAPIRepository"]
constructor() {}
async execute(PublicationAttachmentEntity: PublicationAttachmentEntity): Promise<Result<PublicationAttachmentEntity, PublicationAttachmentEntity>> {
async execute(PublicationAttachmentEntity: PublicationAttachmentEntity): Promise<Result<true, IOUploadError >> {
return new Promise(async (resolve, reject) => {
PublicationAttachmentEntity.chucksManager.clearManualRetry()
let path: string;
const length = PublicationAttachmentEntity.chucksManager.chunks.totalChunks.toString()
const readAndUploadChunk = async(index: number) => {
const chunk = await PublicationAttachmentEntity.chucksManager.chunks.getChunks(index)
const blob = new Blob([chunk]);
const blobFile = new File([blob], "test.mp4", { type: blob.type });
const base64 = await PublicationAttachmentEntity.chucksManager.chunks.getChunks(index)
return this.CMAPIService.FileContent({length, path: PublicationAttachmentEntity.chucksManager.path, index, blobFile})
}
if(!PublicationAttachmentEntity.chucksManager.hasPath()) {
const initIndex = 1
if(index == 2) {
const base1 = await PublicationAttachmentEntity.chucksManager.chunks.getChunks(2)
const uploadRequest = await readAndUploadChunk(initIndex)
// Get the video element from the DOM
const videoElement: any = document.getElementById("yourVideoElementId");
if(uploadRequest.isOk()) {
// Set the src attribute of the video element to the blob URL
videoElement.src = "data:video/mp4;base64,"+ base1 + base64 ;
path = uploadRequest.value.data
PublicationAttachmentEntity.chucksManager.setPath(path)
PublicationAttachmentEntity.chucksManager.setResponse(initIndex, uploadRequest)
alert("passs")
} else {
alert("erro dfsdfsdfsdr")
PublicationAttachmentEntity.chucksManager.clearUploading()
PublicationAttachmentEntity.chucksManager.setManualRetry()
return reject(err(PublicationAttachmentEntity))
// Optionally, you can also set other attributes or play the video
videoElement.controls = true; // Add controls for play, pause, etc.
videoElement.play(); // Auto-play the vid
}
const uploadRequest = this.CMAPIService.FileContent({length, path: PublicationAttachmentEntity.chucksManager.path, index, blobFile: base64})
uploadRequest.then((uploadRequest) => {
if(uploadRequest.isOk()) {
PublicationAttachmentEntity.chucksManager.setResponse(index, uploadRequest)
}
})
return uploadRequest;
}
// if(!PublicationAttachmentEntity.chucksManager.hasPath()) {
// const guidRequest = await this.CMAPIService.RequestUpload()
// if(guidRequest.isOk()) {
// path = guidRequest.value+".mp4"
// PublicationAttachmentEntity.chucksManager.setPath(path)
// } else {
// const pingRequest = await this.CMAPIService.ping()
// if( pingRequest.isErr()) {
// return resolve(err(UploadError.noConnection))
// } else {
// return resolve(err(UploadError.slow))
// }
// }
// }
const allRequest: Promise<any>[] = []
let connection = true
let errorMessage: UploadError.noConnection | UploadError.slow
for (let index = 2; ( (index <= PublicationAttachmentEntity.chucksManager.chunks.totalChunks -1) && connection ); index++) {
for (let index = 1; ( (index <= PublicationAttachmentEntity.chucksManager.chunks.totalChunks) ); index++) {
const needUpload = PublicationAttachmentEntity.chucksManager.needToUploadChunkIndex(index)
if(needUpload) {
const request = readAndUploadChunk(index).then(async(uploadRequest) => {
if(uploadRequest.isErr()) {
const pingRequest = await this.CMAPIService.ping()
if( pingRequest.isErr()) {
connection = false
return reject(err(PublicationAttachmentEntity))
}
} else {
PublicationAttachmentEntity.chucksManager.setResponse(index, uploadRequest)
}
})
allRequest.push(request)
// const request = readAndUploadChunk(index)
// const uploadRequest = await request
// allRequest.push(request)
// if(uploadRequest.isErr()) {
// const pingRequest = await this.CMAPIService.ping()
// if( pingRequest.isErr()) {
// reject(err(PublicationAttachmentEntity))
// }
// } else {
// PublicationAttachmentEntity.chucksManager.setResponse(index, uploadRequest)
// }
}
}
await Promise.all(allRequest)
if(!connection) {
PublicationAttachmentEntity.chucksManager.clearUploading()
PublicationAttachmentEntity.chucksManager.setManualRetry()
return reject(err(PublicationAttachmentEntity))
} else if (PublicationAttachmentEntity.chucksManager.chunks.totalChunks != 1) {
await Promise.all(allRequest)
const uploadRequest = await readAndUploadChunk(PublicationAttachmentEntity.chucksManager.chunks.totalChunks)
if(uploadRequest.isErr()) {
const pingRequest = await this.CMAPIService.ping()
if( pingRequest.isErr()) {
}
PublicationAttachmentEntity.chucksManager.clearUploading()
PublicationAttachmentEntity.chucksManager.setManualRetry()
return reject(err(PublicationAttachmentEntity))
} else {
PublicationAttachmentEntity.chucksManager.setResponse(PublicationAttachmentEntity.chucksManager.chunks.totalChunks, uploadRequest)
PublicationAttachmentEntity.chucksManager.doneChunkUpload()
return resolve(ok(PublicationAttachmentEntity))
}
return resolve(err(errorMessage))
} else {
PublicationAttachmentEntity.chucksManager.doneChunkUpload()
return resolve(ok(PublicationAttachmentEntity))
return resolve(ok(true))
}
})
}
}
@@ -215,7 +199,11 @@ export class PublicationFormMV {
private UploadFileUseCase = new UploadFileUseCase()
private form = new PublicationFormModel()
ObjectMergeNotification = new ObjectMergeNotification()
ObjectMergeNotification = objectMergeNotification
constructor() {
this.ObjectMergeNotification.connect();
}
setDataToFrom(data: IPublicationFormModelEntity) {
this.form.setData(data)
@@ -231,12 +219,14 @@ export class PublicationFormMV {
if(!PublicationAttachmentEntity.hasChunkManger) {
const fileBlob = PublicationAttachmentEntity.blobFile;
const fileChunks = new Chunks({chunkSize: 2000 })
const fileChunks = new Chunks({chunkSize: 70 })
fileChunks.setFile(fileBlob)
PublicationAttachmentEntity.setChunkManger(fileChunks)
PublicationAttachmentEntity.chucksManager.registerOnLastChunk(()=> {
PublicationAttachmentEntity.chucksManager.registerOnLastChunk(() => {
console.log("last chunk ===============================================")
const guid = PublicationAttachmentEntity.chucksManager.path
this.ObjectMergeNotification.subscribe(guid, (data) => {
@@ -246,29 +236,36 @@ export class PublicationFormMV {
})
})
} else {
if(PublicationAttachmentEntity.chucksManager.doneUpload) {
alert("done")
return resolve(true)
}
} else if(PublicationAttachmentEntity.chucksManager.doneUpload) {
return resolve(true)
}
if( PublicationAttachmentEntity.chucksManager.isUploading == false) {
PublicationAttachmentEntity.chucksManager.setUploading()
const result = await this.UploadFileUseCase.execute(PublicationAttachmentEntity)
PublicationAttachmentEntity.chucksManager.clearUploading()
PublicationAttachmentEntity.chucksManager.setManualRetry()
let attemp = 0;
let result: Result<true, IOUploadError>
if( PublicationAttachmentEntity.chucksManager.isUploading == false) {
do {
attemp++
PublicationAttachmentEntity.chucksManager.clearManualRetry()
PublicationAttachmentEntity.chucksManager.setUploading()
result = await this.UploadFileUseCase.execute(PublicationAttachmentEntity)
PublicationAttachmentEntity.chucksManager.clearUploading()
} while (attemp<3 && result.isErr() && result?.error == 'slow')
PublicationAttachmentEntity.chucksManager.setManualRetry()
PublicationAttachmentEntity.chucksManager.doneChunkUpload()
if(result.isErr()) {
alert("error")
reject(false)
resolve(false)
} else {
alert("passs")
resolve(true)
}
} else {
alert("not")
}
})
@@ -276,36 +273,41 @@ export class PublicationFormMV {
}
uploadVideosFiles(): Promise<Boolean> {
return new Promise((resolve, reject)=> {
const videosFiles = this.getVideoFiles()
const videosFilesToUploads = videosFiles.filter( e => e.FileType == "video")
return new Promise((resolve, reject) => {
const Promises: Promise<any>[] = []
// this.ObjectMergeNotification.socket.registerWhenConnected(() => {
const videosFiles = this.getVideoFiles()
for(const file of videosFilesToUploads) {
const promise = this.upload(file)
Promises.push(promise)
}
const videosFilesToUploads = videosFiles.filter( e => e.FileType == "video")
// Use Promise.all to wait for all promises to resolve
Promise.all(Promises)
.then((results) => {
// Check if every promise resolved successfully
const allPromisesResolvedSuccessfully = results.every((result) => result == true);
const Promises: Promise<any>[] = []
if (allPromisesResolvedSuccessfully) {
console.log('All promises resolved successfully.');
resolve(true)
} else {
reject(false)
console.log('Some promises failed to resolve successfully.');
for(const file of videosFilesToUploads) {
const promise = this.upload(file)
Promises.push(promise)
}
})
.catch((error) => {
reject(false)
console.error('An error occurred while resolving promises:', error);
});
// Use Promise.all to wait for all promises to resolve
Promise.all(Promises)
.then((results) => {
// Check if every promise resolved successfully
const allPromisesResolvedSuccessfully = results.every((result) => result == true);
if (allPromisesResolvedSuccessfully) {
console.log('All promises resolved successfully.');
resolve(true)
} else {
resolve(false)
console.log('Some promises failed to resolve successfully.');
}
})
.catch((error) => {
resolve(false)
console.error('An error occurred while resolving promises:', error);
});
//})
})
}
@@ -325,29 +327,22 @@ export class Chunks {
return Math.ceil(this.file.size / this.chunkSize);
}
// Function to read a chunk of the file
readChunk(start: number, end: number): Promise<ArrayBuffer> {
const file = this.file
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
if (reader.result instanceof ArrayBuffer) {
resolve(reader.result);
} else {
reject(new Error("Failed to read chunk"));
}
};
reader.readAsArrayBuffer(file.slice(start, end));
});
}
setFile(file: File) {
this.file = file
}
async getChunks(i: number) {
// Function to read a chunk of the file
readChunk(start: number, end: number): any {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event: any) => resolve(event.target.result.split(',')[1]);
reader.onerror = (error) => reject(error);
reader.readAsDataURL(this.file.slice(start, end));
});
}
async getChunks(i: number): Promise<string> {
i--
if(i < this.totalChunks) {
const start = i * this.chunkSize;
@@ -499,3 +494,4 @@ export class ChucksManager {
this.contentReady = true
}
}