fix: Исправить баг с масштабированием через VIDEOTOOLBOX ускоритель.

feat: добавлена возможность генерировать видео без звука -m --muted
This commit is contained in:
2026-01-22 09:50:51 +03:00
parent 0813bea1d4
commit b8f9f0e046
8 changed files with 113 additions and 70 deletions

View File

@@ -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) {