add some code for future use

see #255
pull/1464/head
Mikael Finstad 3 years ago
parent ebb284c308
commit cd2527e7d7
No known key found for this signature in database
GPG Key ID: 25AB36E3E81CBC26

@ -1057,10 +1057,16 @@ export async function cutEncodeSmartPart({ filePath, cutFrom, cutTo, outPath, ou
function getVideoArgs({ streamIndex, outputIndex }) {
if (streamIndex !== videoStreamIndex) return undefined;
return [
const args = [
`-c:${outputIndex}`, videoCodec,
`-b:${outputIndex}`, videoBitrate,
];
// seems like ffmpeg handles this itself well when encoding same source file
// if (videoLevel != null) args.push(`-level:${outputIndex}`, videoLevel);
// if (videoProfile != null) args.push(`-profile:${outputIndex}`, videoProfile);
return args;
}
const mapStreamsArgs = getMapStreamsArgs({

@ -0,0 +1,80 @@
// This code is for future use (e.g. creating black video to fill in using same codec parameters)
export function parseLevel(videoStream) {
const { level: levelNumeric, codec_name: videoCodec } = videoStream;
if (levelNumeric == null || Number.isNaN(levelNumeric)) return undefined;
if (videoCodec === 'h264') {
if (levelNumeric === 9) return '1b'; // 13 is 1.3. That are all like that (20 is 2.0, etc) except 1b which is 9.
let level = (levelNumeric / 10).toFixed(1); // https://stackoverflow.com/questions/42619191/what-does-level-mean-in-ffprobe-output
if (level >= 0) {
if (level.slice(-2) === '.0') level = level.slice(0, -2); // slice off .0
const validLevels = ['1', '1b', '1.1', '1.2', '1.3', '2', '2.1', '2.2', '3', '3.1', '3.2', '4', '4.1', '4.2', '5', '5.1', '5.2', '6', '6.1', '6.2']; // https://en.wikipedia.org/wiki/Advanced_Video_Coding#Levels
if (validLevels.includes(level)) return level;
}
} else if (videoCodec === 'hevc') {
// Note that on MacOS we don't use x265, but videotoolbox
let level = (levelNumeric / 30).toFixed(1); // https://stackoverflow.com/questions/69983131/whats-the-difference-between-ffprobe-level-and-h-264-level
if (level >= 0) {
if (level.slice(-2) === '.0') level = level.slice(0, -2); // slice off .0
const validLevels = ['1', '2', '2.1', '3', '3.1', '4', '4.1', '5', '5.1', '5.2', '6', '6.1', '6.2']; // https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding_tiers_and_levels
if (validLevels.includes(level)) return level;
}
}
console.warn('Invalid level', videoCodec, levelNumeric);
return undefined;
}
export function parseProfile(videoStream) {
const { profile: ffprobeProfile, codec_name: videoCodec } = videoStream;
let map;
if (videoCodec === 'h264') {
// List of profiles that x264 supports https://trac.ffmpeg.org/wiki/Encode/H.264
// baseline, main, high, high10 (first 10 bit compatible profile), high422 (supports yuv420p, yuv422p, yuv420p10le and yuv422p10le), high444 (supports as above as well as yuv444p and yuv444p10le)
// profiles returned by ffprobe: https://github.com/FFmpeg/FFmpeg/blob/c56f5be6782014fee165d361de1f548eaac7a272/libavcodec/profiles.c#L58
// Not sure about all these...
map = new Map([
['Baseline', { profile: 'baseline', warn: true }],
['Constrained Baseline', { profile: 'baseline', warn: true }],
['Main', { profile: 'main' }],
['Extended', { profile: 'main', warn: true }],
['High', { profile: 'high' }],
['High 10', { profile: 'high10' }],
['High 10 Intra', { profile: 'high10', warn: true }],
['High 4:2:2', { profile: 'high422' }],
['High 4:2:2 Intra', { profile: 'high422', warn: true }],
['High 4:4:4', { profile: 'high444' }],
['High 4:4:4 Predictive', { profile: 'high444', warn: true }],
['High 4:4:4 Intra', { profile: 'high444', warn: true }],
// ['CAVLC 4:4:4', { profile: 'high444', warn: true }],
// ['Multiview High', { profile: 'high', warn: true }],
// ['Stereo High', { profile: 'high', warn: true }],
]);
// Note that on MacOS we don't use x265, but videotoolbox
} else if (videoCodec === 'hevc') {
// List of profiles that x265 supports: https://x265.readthedocs.io/en/master/cli.html#profile-level-tier
// profiles returned by ffprobe: https://github.com/FFmpeg/FFmpeg/blob/c56f5be6782014fee165d361de1f548eaac7a272/libavcodec/profiles.c#L83
map = new Map([
['Main', { profile: 'main' }],
['Main 10', { profile: 'main10' }],
['Main Still Picture', { profile: 'mainstillpicture' }],
// ['Rext', { profile: 'main', warn: true }],
]);
} else {
return undefined;
}
if (!map.has(ffprobeProfile)) {
console.warn('Unknown ffprobe profile', ffprobeProfile);
return undefined;
}
const match = map.get(ffprobeProfile);
if (match.warn) console.warn('Possibly unknown ffprobe profile', ffprobeProfile);
return match.profile;
}

@ -4,6 +4,7 @@ import { readKeyframesAroundTime, findNextKeyframe, findKeyframeAtExactTime } fr
const { stat } = window.require('fs-extra');
// eslint-disable-next-line import/prefer-default-export
export async function getSmartCutParams({ path, videoDuration, desiredCutFrom, streams }) {
const videoStreams = getRealVideoStreams(streams);
@ -51,6 +52,10 @@ export async function getSmartCutParams({ path, videoDuration, desiredCutFrom, s
const timebase = getVideoTimebase(videoStream);
if (timebase == null) console.warn('Unable to determine timebase', videoStream.time_base);
// seems like ffmpeg handles this itself well when encoding same source file
// const videoLevel = parseLevel(videoStream);
// const videoProfile = parseProfile(videoStream);
return {
cutFrom: nextKeyframe.time,
videoStreamIndex: videoStream.index,

@ -287,6 +287,7 @@ export async function deleteFiles({ toDelete, paths: { previewFilePath, sourceFi
if (failedToTrashFiles.length === 0) return; // All good!
// todo allow bypassing trash altogether? https://github.com/mifi/lossless-cut/discussions/1425
const { value } = await Swal.fire({
icon: 'warning',
text: i18n.t('Unable to move file to trash. Do you want to permanently delete it?'),

Loading…
Cancel
Save