fix: Исправить баг с масштабированием через VIDEOTOOLBOX ускоритель.
feat: добавлена возможность генерировать видео без звука -m --muted
This commit is contained in:
@@ -53,6 +53,7 @@ export async function encodeProfileToMP4(
|
||||
codecType: 'h264' | 'av1',
|
||||
qualitySettings?: CodecQualitySettings,
|
||||
optimizations?: VideoOptimizations,
|
||||
muted: boolean = false,
|
||||
decoderAccel?: HardwareAccelerator,
|
||||
onProgress?: (percent: number) => void
|
||||
): Promise<string> {
|
||||
@@ -157,12 +158,14 @@ export async function encodeProfileToMP4(
|
||||
|
||||
// Build video filter chain
|
||||
const filters: string[] = [];
|
||||
const targetWidth = profile.width;
|
||||
const targetHeight = profile.height;
|
||||
|
||||
if (decoderAccel === 'nvenc') {
|
||||
// CUDA path: keep frames on GPU
|
||||
filters.push(`scale_cuda=${profile.width}:${profile.height}`);
|
||||
// CUDA path: вписываем в профиль с сохранением исходного AR
|
||||
filters.push(`scale_cuda=${targetWidth}:${targetHeight}:force_original_aspect_ratio=decrease:force_divisible_by=2`);
|
||||
} else {
|
||||
filters.push(`scale=${profile.width}:${profile.height}`);
|
||||
filters.push(`scale=${targetWidth}:${targetHeight}:force_original_aspect_ratio=decrease:force_divisible_by=2`);
|
||||
}
|
||||
|
||||
// Apply optimizations (for future use)
|
||||
@@ -178,17 +181,26 @@ export async function encodeProfileToMP4(
|
||||
}
|
||||
}
|
||||
|
||||
// Центрируем кадр, чтобы браузеры (Firefox/videotoolbox) не игнорировали PAR
|
||||
filters.push(
|
||||
`pad=${targetWidth}:${targetHeight}:(ow-iw)/2:(oh-ih)/2`,
|
||||
'setsar=1'
|
||||
);
|
||||
|
||||
args.push('-vf', filters.join(','));
|
||||
|
||||
// Audio encoding
|
||||
// Select optimal bitrate based on source (don't upscale)
|
||||
const targetAudioBitrate = parseInt(profile.audioBitrate) || 256;
|
||||
const optimalAudioBitrate = selectAudioBitrate(sourceAudioBitrate, targetAudioBitrate);
|
||||
args.push('-c:a', 'aac', '-b:a', optimalAudioBitrate);
|
||||
|
||||
// Audio optimizations
|
||||
if (optimizations?.audioNormalize) {
|
||||
args.push('-af', 'loudnorm');
|
||||
if (!muted) {
|
||||
// Audio encoding
|
||||
const targetAudioBitrate = parseInt(profile.audioBitrate) || 256;
|
||||
const optimalAudioBitrate = selectAudioBitrate(sourceAudioBitrate, targetAudioBitrate);
|
||||
args.push('-c:a', 'aac', '-b:a', optimalAudioBitrate);
|
||||
|
||||
// Audio optimizations
|
||||
if (optimizations?.audioNormalize) {
|
||||
args.push('-af', 'loudnorm');
|
||||
}
|
||||
} else {
|
||||
args.push('-an'); // без аудио дорожки
|
||||
}
|
||||
|
||||
// Output
|
||||
@@ -217,6 +229,7 @@ export async function encodeProfilesToMP4(
|
||||
codecType: 'h264' | 'av1',
|
||||
qualitySettings?: CodecQualitySettings,
|
||||
optimizations?: VideoOptimizations,
|
||||
muted: boolean = false,
|
||||
decoderAccel?: HardwareAccelerator,
|
||||
onProgress?: (profileName: string, percent: number) => void
|
||||
): Promise<Map<string, string>> {
|
||||
@@ -239,6 +252,7 @@ export async function encodeProfilesToMP4(
|
||||
codecType,
|
||||
qualitySettings,
|
||||
optimizations,
|
||||
muted,
|
||||
decoderAccel,
|
||||
(percent) => {
|
||||
if (onProgress) {
|
||||
@@ -269,6 +283,7 @@ export async function encodeProfilesToMP4(
|
||||
codecType,
|
||||
qualitySettings,
|
||||
optimizations,
|
||||
muted,
|
||||
decoderAccel,
|
||||
(percent) => {
|
||||
if (onProgress) {
|
||||
|
||||
Reference in New Issue
Block a user