refactor: Update merge output format handling

This commit is contained in:
Peifan Li
2025-12-14 15:48:03 -05:00
parent 59a890aab9
commit 98694d5486
2 changed files with 76 additions and 40 deletions

View File

@@ -5,21 +5,21 @@ import { IMAGES_DIR, SUBTITLES_DIR, VIDEOS_DIR } from "../../config/paths";
import { DownloadCancelledError } from "../../errors/DownloadErrors";
import { bccToVtt } from "../../utils/bccToVtt";
import {
calculateDownloadedSize,
formatBytes,
isCancellationError,
isDownloadActive,
parseSize,
calculateDownloadedSize,
formatBytes,
isCancellationError,
isDownloadActive,
parseSize,
} from "../../utils/downloadUtils";
import {
extractBilibiliVideoId,
formatVideoFilename,
extractBilibiliVideoId,
formatVideoFilename,
} from "../../utils/helpers";
import {
executeYtDlpJson,
executeYtDlpSpawn,
getNetworkConfigFromUserConfig,
getUserYtDlpConfig,
executeYtDlpJson,
executeYtDlpSpawn,
getNetworkConfigFromUserConfig,
getUserYtDlpConfig,
} from "../../utils/ytDlpUtils";
import * as storageService from "../storageService";
import { Collection, Video } from "../storageService";
@@ -331,30 +331,39 @@ export class BilibiliDownloader {
);
}
// Prepare base flags from user config (excluding certain overridden options)
// Prepare base flags from user config (excluding output options we manage)
const {
output: _output,
o: _o,
writeSubs: _writeSubs,
writeAutoSubs: _writeAutoSubs,
convertSubs: _convertSubs,
f: _f,
format: _format,
S: _S,
formatSort: _formatSort,
// Extract user subtitle preferences (use them if provided)
writeSubs: userWriteSubs,
writeAutoSubs: userWriteAutoSubs,
convertSubs: userConvertSubs,
// Extract user merge output format (use it if provided)
mergeOutputFormat: userMergeOutputFormat,
...safeUserConfig
} = userConfig;
// Determine merge output format: use user's choice or default to mp4
const mergeOutputFormat = userMergeOutputFormat || "mp4";
console.log(`Using merge output format: ${mergeOutputFormat}`);
// Prepare flags for yt-dlp - merge user config with required settings
const flags: Record<string, any> = {
...networkConfig, // Apply network settings
...safeUserConfig, // Apply other user config
output: outputTemplate,
format: downloadFormat,
mergeOutputFormat: "mp4",
writeSubs: true,
writeAutoSubs: true,
convertSubs: "vtt",
// Use user preferences if provided, otherwise use defaults
mergeOutputFormat: mergeOutputFormat,
writeSubs: userWriteSubs !== undefined ? userWriteSubs : true,
writeAutoSubs:
userWriteAutoSubs !== undefined ? userWriteAutoSubs : true,
convertSubs: userConvertSubs !== undefined ? userConvertSubs : "vtt",
ignoreErrors: true, // Continue even if subtitle download fails
noWarnings: false, // Show warnings for debugging
};
@@ -857,12 +866,16 @@ export class BilibiliDownloader {
`Downloading Bilibili part ${partNumber}/${totalParts}: ${url}`
);
// Get user's yt-dlp configuration for merge output format
const userConfig = getUserYtDlpConfig(url);
const mergeOutputFormat = userConfig.mergeOutputFormat || "mp4";
// Create a safe base filename (without extension)
const timestamp = Date.now();
const safeBaseFilename = `video_${timestamp}`;
// Add extensions for video and thumbnail
const videoFilename = `${safeBaseFilename}.mp4`;
// Add extensions for video and thumbnail (use user's format preference)
const videoFilename = `${safeBaseFilename}.${mergeOutputFormat}`;
const thumbnailFilename = `${safeBaseFilename}.jpg`;
// Set full paths for video and thumbnail
@@ -926,7 +939,7 @@ export class BilibiliDownloader {
videoAuthor,
videoDate
);
const newVideoFilename = `${newSafeBaseFilename}.mp4`;
const newVideoFilename = `${newSafeBaseFilename}.${mergeOutputFormat}`;
const newThumbnailFilename = `${newSafeBaseFilename}.jpg`;
// Rename the files

View File

@@ -321,8 +321,8 @@ export class YtDlpDownloader {
const newVideoPath = path.join(VIDEOS_DIR, finalVideoFilename);
const newThumbnailPath = path.join(IMAGES_DIR, finalThumbnailFilename);
// Download the video
console.log("Downloading video to:", newVideoPath);
// Note: newVideoPath will be updated below based on merge output format
console.log("Preparing video download path:", newVideoPath);
if (downloadId) {
storageService.updateActiveDownload(downloadId, {
@@ -348,32 +348,55 @@ export class YtDlpDownloader {
console.log("Using user-specified format:", userFormat);
}
// Prepare base flags from user config (excluding certain overridden options)
// Prepare base flags from user config (excluding output options we manage)
const {
output: _output, // Ignore user output template (we manage this)
o: _o,
writeSubs: _writeSubs, // We always enable subtitles
writeAutoSubs: _writeAutoSubs,
convertSubs: _convertSubs,
f: _f, // Format is handled specially above
format: _format,
S: userFormatSort, // Format sort is handled specially
formatSort: userFormatSort2,
// Extract user subtitle preferences (use them if provided)
writeSubs: userWriteSubs,
writeAutoSubs: userWriteAutoSubs,
convertSubs: userConvertSubs,
// Extract user merge output format (use it if provided)
mergeOutputFormat: userMergeOutputFormat,
...safeUserConfig
} = userConfig;
// Get format sort option if user specified it
const formatSortValue = userFormatSort || userFormatSort2;
// Prepare flags - user config first, then our required overrides
// Determine merge output format: use user's choice or default to mp4
const mergeOutputFormat = userMergeOutputFormat || "mp4";
// Update the video path to use the correct extension based on merge format
const videoExtension = mergeOutputFormat;
const newVideoPathWithFormat = newVideoPath.replace(
/\.mp4$/,
`.${videoExtension}`
);
finalVideoFilename = finalVideoFilename.replace(
/\.mp4$/,
`.${videoExtension}`
);
console.log(
`Using merge output format: ${mergeOutputFormat}, downloading to: ${newVideoPathWithFormat}`
);
// Prepare flags - defaults first, then user config to allow overrides
const flags: Record<string, any> = {
...safeUserConfig, // Apply user config first
output: newVideoPath, // Always use our output path
...safeUserConfig, // Apply user config
output: newVideoPathWithFormat, // Always use our output path with correct extension
format: defaultFormat,
mergeOutputFormat: "mp4",
writeSubs: true,
writeAutoSubs: true,
convertSubs: "vtt",
// Use user preferences if provided, otherwise use defaults
mergeOutputFormat: mergeOutputFormat,
writeSubs: userWriteSubs !== undefined ? userWriteSubs : true,
writeAutoSubs:
userWriteAutoSubs !== undefined ? userWriteAutoSubs : true,
convertSubs: userConvertSubs !== undefined ? userConvertSubs : "vtt",
// Only add PO token provider if configured
...(PROVIDER_SCRIPT
? {
@@ -427,7 +450,7 @@ export class YtDlpDownloader {
// Clean up partial files
console.log("Cleaning up partial files...");
cleanupPartialVideoFiles(newVideoPath);
cleanupPartialVideoFiles(newVideoPathWithFormat);
cleanupPartialVideoFiles(newThumbnailPath);
cleanupSubtitleFiles(newSafeBaseFilename);
});
@@ -487,7 +510,7 @@ export class YtDlpDownloader {
} catch (error: any) {
if (isCancellationError(error)) {
console.log("Download was cancelled");
cleanupPartialVideoFiles(newVideoPath);
cleanupPartialVideoFiles(newVideoPathWithFormat);
cleanupSubtitleFiles(newSafeBaseFilename);
throw DownloadCancelledError.create();
}
@@ -501,7 +524,7 @@ export class YtDlpDownloader {
if (isSubtitleError) {
// Check if video file was successfully downloaded
if (fs.existsSync(newVideoPath)) {
if (fs.existsSync(newVideoPathWithFormat)) {
console.warn(
"Subtitle download failed, but video was downloaded successfully. Continuing...",
error.message
@@ -524,7 +547,7 @@ export class YtDlpDownloader {
// Check if download was cancelled (it might have been removed from active downloads)
if (!isDownloadActive(downloadId)) {
console.log("Download was cancelled (no longer in active downloads)");
cleanupPartialVideoFiles(newVideoPath);
cleanupPartialVideoFiles(newVideoPathWithFormat);
cleanupSubtitleFiles(newSafeBaseFilename);
throw DownloadCancelledError.create();
}