More flexible convert to friendly format

#297 #160
pull/304/head
Mikael Finstad 2020-04-10 15:51:35 +08:00
rodzic ec1759c965
commit 62189f2294
2 zmienionych plików z 78 dodań i 40 usunięć

Wyświetl plik

@ -853,20 +853,6 @@ const App = memo(() => {
});
}, [playing, filePath]);
const onVideoError = useCallback(() => {
const { error } = videoRef.current;
if (!error) return;
if (!fileUri) return; // Probably MEDIA_ELEMENT_ERROR: Empty src attribute
console.error(error.message);
const MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
if (error.code === MEDIA_ERR_SRC_NOT_SUPPORTED && !dummyVideoPath) {
console.log('MEDIA_ERR_SRC_NOT_SUPPORTED - trying to create dummy');
tryCreateDummyVideo();
}
}, [tryCreateDummyVideo, fileUri, dummyVideoPath]);
const deleteSource = useCallback(async () => {
if (!filePath) return;
@ -1094,7 +1080,7 @@ const App = memo(() => {
setHtml5FriendlyPath(html5FriendlyPathRequested);
showUnsupportedFileMessage();
} else if (
!(await checkAndSetExistingHtml5FriendlyFile('slow-audio') || await checkAndSetExistingHtml5FriendlyFile('slow') || await checkAndSetExistingHtml5FriendlyFile('fast'))
!(await checkAndSetExistingHtml5FriendlyFile('slowest') || await checkAndSetExistingHtml5FriendlyFile('slow-audio') || await checkAndSetExistingHtml5FriendlyFile('slow') || await checkAndSetExistingHtml5FriendlyFile('fast-audio') || await checkAndSetExistingHtml5FriendlyFile('fast'))
&& !doesPlayerSupportFile(streams)
) {
await createDummyVideo(cod, fp);
@ -1274,6 +1260,40 @@ const App = memo(() => {
userOpenFiles(filePaths);
}, [userOpenFiles, loadEdlFile]);
const html5ifyInternal = useCallback(async ({ customOutDir: cod, filePath: fp, speed, hasAudio: ha, hasVideo: hv }) => {
const path = getHtml5ifiedPath(cod, fp, speed);
const includeVideo = hv;
const includeAudio = ['fast-audio', 'slow-audio', 'slowest'].includes(speed) && ha;
const encode = ['slow-audio', 'slow', 'slowest'].includes(speed);
const highQuality = speed === 'slowest';
await ffmpegHtml5ify({ filePath: fp, outPath: path, encode, includeVideo, includeAudio, highQuality });
return path;
}, [getHtml5ifiedPath]);
const html5ifyAndLoad = useCallback(async (speed) => {
const path = await html5ifyInternal({ customOutDir, filePath, speed, hasAudio, hasVideo });
load({ filePath, html5FriendlyPathRequested: path, customOutDir });
}, [hasAudio, hasVideo, customOutDir, filePath, html5ifyInternal, load]);
const onVideoError = useCallback(async () => {
const { error } = videoRef.current;
if (!error) return;
if (!fileUri) return; // Probably MEDIA_ELEMENT_ERROR: Empty src attribute
console.error(error.message);
const MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
if (error.code === MEDIA_ERR_SRC_NOT_SUPPORTED && !dummyVideoPath) {
console.log('MEDIA_ERR_SRC_NOT_SUPPORTED - trying to create dummy');
if (hasVideo) tryCreateDummyVideo();
else {
toast.fire({ icon: 'info', text: 'This file does not have any supported. Encoding a preview file...' });
await html5ifyAndLoad('slow-audio');
}
}
}, [tryCreateDummyVideo, fileUri, dummyVideoPath, hasVideo, html5ifyAndLoad]);
useEffect(() => {
function fileOpened(event, filePaths) {
userOpenFiles(filePaths);
@ -1290,9 +1310,11 @@ const App = memo(() => {
async function askForHtml5ifySpeed(allowedOptions) {
const availOptions = {
fastest: i18n.t('Fastest: Low playback speed (no audio)'),
fast: i18n.t('Fast: Full quality remux, unlikely to work'),
slow: i18n.t('Slow: Low video quality encode (no audio)'),
'slow-audio': i18n.t('Slowest: Low video/audio quality encode'),
fast: i18n.t('Fast: Full quality remux (no audio), likely to fail'),
'fast-audio': i18n.t('Fast: Full quality remux, likely to fail'),
slow: i18n.t('Slow: Low quality encode (no audio)'),
'slow-audio': i18n.t('Slow: Low quality encode'),
slowest: i18n.t('Slowest: High quality encode'),
};
const inputOptions = {};
allowedOptions.forEach((allowedOption) => {
@ -1313,28 +1335,19 @@ const App = memo(() => {
return value;
}
async function html5ifyInternal({ customOutDir: cod, filePath: fp, speed, hasAudio: ha, hasVideo: hv }) {
const path = getHtml5ifiedPath(cod, fp, speed);
const encodeVideo = ['slow', 'slow-audio'].includes(speed) && hv;
const encodeAudio = speed === 'slow-audio' && ha;
await ffmpegHtml5ify(fp, path, encodeVideo, encodeAudio);
return path;
}
async function html5ify() {
if (!filePath) return;
try {
setWorking(true);
const speed = await askForHtml5ifySpeed(['fastest', 'fast', 'slow', 'slow-audio']);
const speed = await askForHtml5ifySpeed(['fastest', 'fast-audio', 'fast', 'slow', 'slow-audio', 'slowest']);
if (!speed) return;
if (speed === 'fastest') {
await createDummyVideo(customOutDir, filePath);
} else if (['fast', 'slow', 'slow-audio'].includes(speed)) {
const path = await html5ifyInternal({ customOutDir, filePath, speed, hasAudio, hasVideo });
load({ filePath, html5FriendlyPathRequested: path, customOutDir });
} else if (['fast-audio', 'fast', 'slow', 'slow-audio', 'slowest'].includes(speed)) {
await html5ifyAndLoad(speed);
}
} catch (err) {
errorToast(i18n.t('Failed to html5ify file'));
@ -1416,7 +1429,7 @@ const App = memo(() => {
const failedFiles = [];
let i = 0;
const speed = await askForHtml5ifySpeed(['fast', 'slow', 'slow-audio']);
const speed = await askForHtml5ifySpeed(['fast-audio', 'fast', 'slow', 'slow-audio', 'slowest']);
if (!speed) return;
try {
@ -1486,9 +1499,9 @@ const App = memo(() => {
electron.ipcRenderer.removeListener('batchConvertFriendlyFormat', batchConvertFriendlyFormat);
};
}, [
load, mergeFiles, outputDir, filePath, isFileOpened, customOutDir, startTimeOffset, getHtml5ifiedPath,
mergeFiles, outputDir, filePath, isFileOpened, customOutDir, startTimeOffset,
createDummyVideo, resetState, extractAllStreams, userOpenFiles, cutSegmentsHistory,
loadEdlFile, cutSegments, edlFilePath, askBeforeClose, toggleHelp, toggleSettings, assureOutDirAccess, hasAudio, hasVideo,
loadEdlFile, cutSegments, edlFilePath, askBeforeClose, toggleHelp, toggleSettings, assureOutDirAccess, html5ifyAndLoad, html5ifyInternal,
]);
async function showAddStreamSourceDialog() {

Wyświetl plik

@ -306,18 +306,43 @@ export async function cutMultiple({
return outFiles;
}
export async function html5ify(filePath, outPath, encodeVideo, encodeAudio) {
console.log('Making HTML5 friendly version', { filePath, outPath, encodeVideo });
export async function html5ify({ filePath, outPath, encode, includeVideo, includeAudio, highQuality }) {
console.log('Making HTML5 friendly version', { filePath, outPath, encode, includeVideo, includeAudio, highQuality });
let videoArgs;
if (!encodeVideo) videoArgs = ['-vcodec', 'copy'];
else if (os.platform() === 'darwin') {
videoArgs = ['-vf', 'scale=-2:400,format=yuv420p', '-allow_sw', '1', '-sws_flags', 'lanczos', '-vcodec', 'h264', '-b:v', '1500k'];
let audioArgs;
if (includeVideo) {
if (!encode) {
videoArgs = ['-vcodec', 'copy'];
} else if (os.platform() === 'darwin') {
if (highQuality) {
videoArgs = ['-vf', 'format=yuv420p', '-allow_sw', '1', '-vcodec', 'h264', '-b:v', '15M'];
} else {
videoArgs = ['-vf', 'scale=-2:400,format=yuv420p', '-allow_sw', '1', '-sws_flags', 'lanczos', '-vcodec', 'h264', '-b:v', '1500k'];
}
} else if (highQuality) {
videoArgs = ['-vf', 'format=yuv420p', '-vcodec', 'libx264', '-profile:v', 'high', '-preset:v', 'slow', '-crf', '17'];
} else {
videoArgs = ['-vf', 'scale=-2:400,format=yuv420p', '-sws_flags', 'neighbor', '-vcodec', 'libx264', '-profile:v', 'baseline', '-x264opts', 'level=3.0', '-preset:v', 'ultrafast', '-crf', '28'];
}
} else {
videoArgs = ['-vf', 'scale=-2:400,format=yuv420p', '-sws_flags', 'neighbor', '-vcodec', 'libx264', '-profile:v', 'baseline', '-x264opts', 'level=3.0', '-preset:v', 'ultrafast', '-crf', '28'];
videoArgs = ['-vn'];
}
const audioArgs = encodeAudio ? ['-acodec', 'aac', '-ar', '44100', '-ac', '2', '-b:a', '96k'] : ['-an'];
if (includeAudio) {
if (encode) {
if (highQuality) {
audioArgs = ['-acodec', 'aac', '-b:a', '192k'];
} else {
audioArgs = ['-acodec', 'aac', '-ar', '44100', '-ac', '2', '-b:a', '96k'];
}
} else {
audioArgs = ['-acodec', 'copy'];
}
} else {
audioArgs = ['-an'];
}
const ffmpegArgs = [
'-hide_banner',