fixed issues with video conversion
This commit is contained in:
parent
b861a8d358
commit
6188c9eed4
|
@ -10,6 +10,7 @@ class FFmpegService {
|
|||
private fileReader: FileReader = null;
|
||||
|
||||
private generateThumbnailProcessor = new QueueProcessor<Uint8Array>(1);
|
||||
private generateMP4ConversionProcessor = new QueueProcessor<Uint8Array>(1);
|
||||
async init() {
|
||||
try {
|
||||
this.ffmpeg = createFFmpeg({
|
||||
|
@ -57,7 +58,10 @@ class FFmpegService {
|
|||
}
|
||||
}
|
||||
|
||||
async convertLivePhotoToMP4(file: Uint8Array): Promise<Uint8Array> {
|
||||
async convertToMP4(
|
||||
file: Uint8Array,
|
||||
fileName: string
|
||||
): Promise<Uint8Array> {
|
||||
if (!this.ffmpeg) {
|
||||
await this.init();
|
||||
}
|
||||
|
@ -65,30 +69,23 @@ class FFmpegService {
|
|||
await this.isLoading;
|
||||
}
|
||||
|
||||
const response = this.generateMP4ConversionProcessor.queueUpRequest(
|
||||
convertToMP4Helper.bind(null, this.ffmpeg, file, fileName)
|
||||
);
|
||||
|
||||
try {
|
||||
this.ffmpeg.FS('writeFile', 'input.mov', file);
|
||||
console.log('starting encoding', new Date().toLocaleTimeString());
|
||||
await this.ffmpeg.run(
|
||||
'-i',
|
||||
'input.mov',
|
||||
'-preset',
|
||||
'ultrafast',
|
||||
'output.mp4'
|
||||
);
|
||||
const convertedFile = await this.ffmpeg.FS(
|
||||
'readFile',
|
||||
'output.mp4'
|
||||
);
|
||||
console.log('done encoding', new Date().toLocaleTimeString());
|
||||
await this.ffmpeg.FS('unlink', 'input.mov');
|
||||
await this.ffmpeg.FS('unlink', 'output.mp4');
|
||||
return convertedFile;
|
||||
return await response.promise;
|
||||
} catch (e) {
|
||||
logError(e, 'ffmpeg live photo to MP4 conversion failed');
|
||||
if (e.message === CustomError.REQUEST_CANCELLED) {
|
||||
// ignore
|
||||
return null;
|
||||
} else {
|
||||
logError(e, 'ffmpeg MP4 conversion failed');
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function generateThumbnailHelper(
|
||||
ffmpeg: FFmpeg,
|
||||
|
@ -133,4 +130,28 @@ async function generateThumbnailHelper(
|
|||
}
|
||||
}
|
||||
|
||||
async function convertToMP4Helper(
|
||||
ffmpeg: FFmpeg,
|
||||
file: Uint8Array,
|
||||
inputFileName: string
|
||||
) {
|
||||
try {
|
||||
ffmpeg.FS('writeFile', inputFileName, file);
|
||||
await ffmpeg.run(
|
||||
'-i',
|
||||
inputFileName,
|
||||
'-preset',
|
||||
'ultrafast',
|
||||
'output.mp4'
|
||||
);
|
||||
const convertedFile = await ffmpeg.FS('readFile', 'output.mp4');
|
||||
ffmpeg.FS('unlink', inputFileName);
|
||||
ffmpeg.FS('unlink', 'output.mp4');
|
||||
return convertedFile;
|
||||
} catch (e) {
|
||||
logError(e, 'ffmpeg MP4 conversion failed');
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
export default new FFmpegService();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import JSZip from 'jszip';
|
||||
import { fileExtensionWithDot } from 'utils/file';
|
||||
import FFmpegService from 'services/ffmpegService';
|
||||
|
||||
class MotionPhoto {
|
||||
image: Uint8Array;
|
||||
|
@ -26,9 +25,8 @@ export const decodeMotionPhoto = async (
|
|||
} else if (zipFilename.startsWith('video')) {
|
||||
motionPhoto.videoNameTitle =
|
||||
originalName + fileExtensionWithDot(zipFilename);
|
||||
const video = await zip.files[zipFilename].async('uint8array');
|
||||
motionPhoto.video = await FFmpegService.convertLivePhotoToMP4(
|
||||
video
|
||||
motionPhoto.video = await zip.files[zipFilename].async(
|
||||
'uint8array'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import {
|
|||
} from 'constants/file';
|
||||
import PublicCollectionDownloadManager from 'services/publicCollectionDownloadManager';
|
||||
import HEICConverter from 'services/HEICConverter';
|
||||
import ffmpegService from 'services/ffmpegService';
|
||||
|
||||
export function downloadAsFile(filename: string, content: string) {
|
||||
const file = new Blob([content], {
|
||||
|
@ -353,7 +354,13 @@ export async function splitLivePhoto(file: EnteFile, url: string) {
|
|||
const originalName = fileNameWithoutExtension(file.metadata.title);
|
||||
const motionPhoto = await decodeMotionPhoto(fileBlob, originalName);
|
||||
let image = new Blob([motionPhoto.image]);
|
||||
const video = new Blob([motionPhoto.video]);
|
||||
|
||||
// can run conversion in parellel as video and image
|
||||
// have different processes
|
||||
const convertedVideo = ffmpegService.convertToMP4(
|
||||
motionPhoto.video,
|
||||
motionPhoto.videoNameTitle
|
||||
);
|
||||
|
||||
const typeFromExtension = getFileExtension(motionPhoto.imageNameTitle);
|
||||
const reader = new FileReader();
|
||||
|
@ -363,6 +370,9 @@ export async function splitLivePhoto(file: EnteFile, url: string) {
|
|||
if (isFileHEIC(mimeType)) {
|
||||
image = await HEICConverter.convert(image);
|
||||
}
|
||||
|
||||
const video = new Blob([await convertedVideo]);
|
||||
|
||||
const imageURL = URL.createObjectURL(image);
|
||||
const videoURL = URL.createObjectURL(video);
|
||||
return { imageURL, videoURL };
|
||||
|
|
Loading…
Reference in a new issue