More flexible convert to friendly format

#297 #160
pull/304/head
Mikael Finstad 6 years ago
parent ec1759c965
commit 62189f2294

@ -853,20 +853,6 @@ const App = memo(() => {
}); });
}, [playing, filePath]); }, [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 () => { const deleteSource = useCallback(async () => {
if (!filePath) return; if (!filePath) return;
@ -1094,7 +1080,7 @@ const App = memo(() => {
setHtml5FriendlyPath(html5FriendlyPathRequested); setHtml5FriendlyPath(html5FriendlyPathRequested);
showUnsupportedFileMessage(); showUnsupportedFileMessage();
} else if ( } 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) && !doesPlayerSupportFile(streams)
) { ) {
await createDummyVideo(cod, fp); await createDummyVideo(cod, fp);
@ -1274,6 +1260,40 @@ const App = memo(() => {
userOpenFiles(filePaths); userOpenFiles(filePaths);
}, [userOpenFiles, loadEdlFile]); }, [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(() => { useEffect(() => {
function fileOpened(event, filePaths) { function fileOpened(event, filePaths) {
userOpenFiles(filePaths); userOpenFiles(filePaths);
@ -1290,9 +1310,11 @@ const App = memo(() => {
async function askForHtml5ifySpeed(allowedOptions) { async function askForHtml5ifySpeed(allowedOptions) {
const availOptions = { const availOptions = {
fastest: i18n.t('Fastest: Low playback speed (no audio)'), fastest: i18n.t('Fastest: Low playback speed (no audio)'),
fast: i18n.t('Fast: Full quality remux, unlikely to work'), fast: i18n.t('Fast: Full quality remux (no audio), likely to fail'),
slow: i18n.t('Slow: Low video quality encode (no audio)'), 'fast-audio': i18n.t('Fast: Full quality remux, likely to fail'),
'slow-audio': i18n.t('Slowest: Low video/audio quality encode'), 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 = {}; const inputOptions = {};
allowedOptions.forEach((allowedOption) => { allowedOptions.forEach((allowedOption) => {
@ -1313,28 +1335,19 @@ const App = memo(() => {
return value; 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() { async function html5ify() {
if (!filePath) return; if (!filePath) return;
try { try {
setWorking(true); 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) return;
if (speed === 'fastest') { if (speed === 'fastest') {
await createDummyVideo(customOutDir, filePath); await createDummyVideo(customOutDir, filePath);
} else if (['fast', 'slow', 'slow-audio'].includes(speed)) { } else if (['fast-audio', 'fast', 'slow', 'slow-audio', 'slowest'].includes(speed)) {
const path = await html5ifyInternal({ customOutDir, filePath, speed, hasAudio, hasVideo }); await html5ifyAndLoad(speed);
load({ filePath, html5FriendlyPathRequested: path, customOutDir });
} }
} catch (err) { } catch (err) {
errorToast(i18n.t('Failed to html5ify file')); errorToast(i18n.t('Failed to html5ify file'));
@ -1416,7 +1429,7 @@ const App = memo(() => {
const failedFiles = []; const failedFiles = [];
let i = 0; 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; if (!speed) return;
try { try {
@ -1486,9 +1499,9 @@ const App = memo(() => {
electron.ipcRenderer.removeListener('batchConvertFriendlyFormat', batchConvertFriendlyFormat); electron.ipcRenderer.removeListener('batchConvertFriendlyFormat', batchConvertFriendlyFormat);
}; };
}, [ }, [
load, mergeFiles, outputDir, filePath, isFileOpened, customOutDir, startTimeOffset, getHtml5ifiedPath, mergeFiles, outputDir, filePath, isFileOpened, customOutDir, startTimeOffset,
createDummyVideo, resetState, extractAllStreams, userOpenFiles, cutSegmentsHistory, 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() { async function showAddStreamSourceDialog() {

@ -306,18 +306,43 @@ export async function cutMultiple({
return outFiles; return outFiles;
} }
export async function html5ify(filePath, outPath, encodeVideo, encodeAudio) { export async function html5ify({ filePath, outPath, encode, includeVideo, includeAudio, highQuality }) {
console.log('Making HTML5 friendly version', { filePath, outPath, encodeVideo }); console.log('Making HTML5 friendly version', { filePath, outPath, encode, includeVideo, includeAudio, highQuality });
let videoArgs; let videoArgs;
if (!encodeVideo) videoArgs = ['-vcodec', 'copy']; let audioArgs;
else if (os.platform() === 'darwin') {
videoArgs = ['-vf', 'scale=-2:400,format=yuv420p', '-allow_sw', '1', '-sws_flags', 'lanczos', '-vcodec', 'h264', '-b:v', '1500k']; 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 { } 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 = [ const ffmpegArgs = [
'-hide_banner', '-hide_banner',

Loading…
Cancel
Save