improve bt2020 handling

pull/1653/merge
Mikael Finstad 2 weeks ago
parent 251013c6de
commit 25101325f7
No known key found for this signature in database
GPG Key ID: 25AB36E3E81CBC26

@ -550,7 +550,29 @@ export function createMediaSourceProcess({ path, videoStreamIndex, audioStreamIn
if (videoStreamIndex != null) {
const videoFilters: string[] = [];
if (fps != null) videoFilters.push(`fps=${fps}`);
if (size != null) videoFilters.push(`scale=${size}:${size}:flags=lanczos:force_original_aspect_ratio=decrease:force_divisible_by=2`);
const scaleFilterOptions: string[] = [];
if (size != null) scaleFilterOptions.push(`${size}:${size}:flags=lanczos:force_original_aspect_ratio=decrease:force_divisible_by=2`);
// we need to reduce the color space to bt709 for compatibility with most OS'es and hardware combinations
// especially because of this bug https://github.com/electron/electron/issues/47947
// see also https://www.reddit.com/r/ffmpeg/comments/jlk2zn/how_to_encode_using_bt709/
scaleFilterOptions.push('in_color_matrix=auto:in_range=auto:out_color_matrix=bt709:out_range=tv');
if (scaleFilterOptions.length > 0) videoFilters.push(`scale=${scaleFilterOptions.join(':')}`);
// alternatively we could have used `tonemap=hable` instead, but it's slower because it's an additional separate filter.
// videoFilters.push('tonemap=hable');
// the best would be to use zscale, but it's not yet available in our ffmpeg build, and I think it's slower.
// https://gist.github.com/goyuix/033d35846b05733d77f568b754e7c3ea
// https://superuser.com/questions/1732301/convert-10bit-hdr-video-to-8bit-frames/1732684#1732684
videoFilters.push(
// most compatible pixel format:
'format=yuv420p',
// setparams is always needed when converting hdr to sdr:
'setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709',
);
const videoFiltersStr = videoFilters.length > 0 ? videoFilters.join(',') : 'null';
graph.push(`[0:${videoStreamIndex}]${videoFiltersStr}[video]`);
}
@ -576,11 +598,6 @@ export function createMediaSourceProcess({ path, videoStreamIndex, audioStreamIn
const videoEncodeArgs = [
'libx264', '-preset', 'ultrafast', '-tune', 'zerolatency', '-crf', '10',
// should, in theory, set the private options of x264 or x265 automatically
// https://www.reddit.com/r/ffmpeg/comments/jlk2zn/how_to_encode_using_bt709/
'-colorspace:v', 'bt709', '-color_primaries:v', 'bt709', '-color_trc:v', 'bt709', '-color_range:v', 'tv',
'-pix_fmt:v', 'yuv420p',
];
// const videoEncodeArgs = ['h264_videotoolbox', '-b:v', '5M']

@ -75,6 +75,7 @@ import {
isAbortedError,
withErrorHandling,
shootConfetti,
isMasBuild,
} from './util';
import { toast, errorToast, showPlaybackFailedMessage } from './swal';
import { adjustRate } from './util/rate-calculator';
@ -1444,7 +1445,7 @@ function App() {
const existingHtml5FriendlyFile = await findExistingHtml5FriendlyFile(fp, cod);
const needsAutoHtml5ify = !existingHtml5FriendlyFile && !willPlayerProperlyHandleVideo({ streams: fileMeta.streams, hevcPlaybackSupported }) && validDuration;
const needsAutoHtml5ify = !existingHtml5FriendlyFile && !willPlayerProperlyHandleVideo({ streams: fileMeta.streams, hevcPlaybackSupported, isMasBuild }) && validDuration;
console.log('loadMedia', { filePath: fp, customOutDir: cod, projectPath });

@ -1,7 +1,6 @@
import invariant from 'tiny-invariant';
import { FFprobeStream, FFprobeStreamDisposition } from '../../../../ffprobe';
import { AllFilesMeta, ChromiumHTMLAudioElement, ChromiumHTMLVideoElement, CopyfileStreams, LiteFFprobeStream } from '../types';
import { isMasBuild } from '../util';
// taken from `ffmpeg -codecs`
@ -368,8 +367,10 @@ export async function doesPlayerSupportHevcPlayback() {
// so we will detect these codecs and convert to dummy
// "properly handle" here means either play it back or give a playback error if the video codec is not supported
// todo maybe improve https://github.com/mifi/lossless-cut/issues/88#issuecomment-1363828563
export function willPlayerProperlyHandleVideo({ streams, hevcPlaybackSupported }: {
streams: FFprobeStream[], hevcPlaybackSupported: boolean,
export function willPlayerProperlyHandleVideo({ streams, hevcPlaybackSupported, isMasBuild }: {
streams: FFprobeStream[],
hevcPlaybackSupported: boolean,
isMasBuild: boolean,
}) {
const realVideoStreams = getRealVideoStreams(streams);
// If audio-only format, assume all is OK
@ -378,7 +379,7 @@ export function willPlayerProperlyHandleVideo({ streams, hevcPlaybackSupported }
// https://github.com/mifi/lossless-cut/issues/2562
// https://github.com/mifi/lossless-cut/issues/2548
// https://github.com/electron/electron/issues/47947
if (isMasBuild && realVideoStreams.some((s) => s.pix_fmt === 'yuv420p10le' && s.color_space === 'bt2020nc' && s.color_primaries === 'bt2020')) {
if (isMasBuild && realVideoStreams.some((s) => s.color_space != null && ['bt2020nc', 'bt2020_ncl', 'bt2020c', 'bt2020_cl'].includes(s.color_space) && s.color_primaries === 'bt2020')) {
return false;
}

Loading…
Cancel
Save