This commit is contained in:
2025-11-09 10:40:35 +03:00
parent 3086d6907c
commit 8c61e0e9db
6 changed files with 352 additions and 27 deletions

View File

@@ -15,8 +15,8 @@ import {
getVideoMetadata,
ensureDir
} from '../utils';
import { selectProfiles } from '../config/profiles';
import { generateThumbnailSprite } from './thumbnails';
import { selectProfiles, createProfilesFromStrings } from '../config/profiles';
import { generateThumbnailSprite, generatePoster } from './thumbnails';
import { encodeProfilesToMP4 } from './encoding';
import { packageToDash } from './packaging';
@@ -32,9 +32,12 @@ export async function convertToDash(
outputDir,
segmentDuration = 2,
profiles: userProfiles,
customProfiles,
useNvenc,
generateThumbnails = true,
thumbnailConfig = {},
generatePoster: shouldGeneratePoster = true,
posterTimecode = '00:00:01',
parallel = true,
onProgress
} = options;
@@ -50,9 +53,12 @@ export async function convertToDash(
tempDir,
segmentDuration,
userProfiles,
customProfiles,
useNvenc,
generateThumbnails,
thumbnailConfig,
shouldGeneratePoster,
posterTimecode,
parallel,
onProgress
);
@@ -75,9 +81,12 @@ async function convertToDashInternal(
tempDir: string,
segmentDuration: number,
userProfiles: VideoProfile[] | undefined,
customProfiles: string[] | undefined,
useNvenc: boolean | undefined,
generateThumbnails: boolean,
thumbnailConfig: ThumbnailConfig,
generatePosterFlag: boolean,
posterTimecode: string,
parallel: boolean,
onProgress?: (progress: ConversionProgress) => void
): Promise<DashConvertResult> {
@@ -112,12 +121,44 @@ async function convertToDashInternal(
}
// Select profiles
const profiles = userProfiles || selectProfiles(
metadata.width,
metadata.height,
metadata.fps,
metadata.videoBitrate
);
let profiles: VideoProfile[];
if (customProfiles && customProfiles.length > 0) {
// User specified custom profiles via CLI
const result = createProfilesFromStrings(
customProfiles,
metadata.width,
metadata.height,
metadata.fps,
metadata.videoBitrate
);
// Show errors if any
if (result.errors.length > 0) {
console.warn('\n⚠ Profile warnings:');
for (const error of result.errors) {
console.warn(` - ${error}`);
}
console.warn('');
}
profiles = result.profiles;
if (profiles.length === 0) {
throw new Error('No valid profiles found in custom list. Check warnings above.');
}
} else if (userProfiles) {
// Programmatic API usage
profiles = userProfiles;
} else {
// Default: auto-select based on source
profiles = selectProfiles(
metadata.width,
metadata.height,
metadata.fps,
metadata.videoBitrate
);
}
if (profiles.length === 0) {
throw new Error('No suitable profiles found for input video resolution');
@@ -126,6 +167,14 @@ async function convertToDashInternal(
// Create video name directory
const inputBasename = basename(input, extname(input));
const videoOutputDir = join(outputDir, inputBasename);
// Clean up previous conversion if exists
try {
await rm(videoOutputDir, { recursive: true, force: true });
} catch (err) {
// Directory might not exist, that's fine
}
await ensureDir(videoOutputDir);
reportProgress('analyzing', 20, `Using ${willUseNvenc ? 'NVENC' : 'CPU'} encoding`, undefined);
@@ -212,6 +261,21 @@ async function convertToDashInternal(
reportProgress('thumbnails', 90, 'Thumbnails generated');
}
// Generate poster
let posterPath: string | undefined;
if (generatePosterFlag) {
reportProgress('thumbnails', 92, 'Generating poster image...');
posterPath = await generatePoster(
input,
videoOutputDir,
posterTimecode
);
reportProgress('thumbnails', 95, 'Poster generated');
}
// Generate MPD manifest
reportProgress('manifest', 95, 'Finalizing manifest...');
@@ -226,6 +290,7 @@ async function convertToDashInternal(
videoPaths,
thumbnailSpritePath,
thumbnailVttPath,
posterPath,
duration: metadata.duration,
profiles,
usedNvenc: willUseNvenc