From 7f79fc8761f0ef46589e4ffba5fbc2264bebf794 Mon Sep 17 00:00:00 2001 From: Subhamoy Biswas Date: Thu, 10 Jul 2025 23:31:40 +0530 Subject: [PATCH] (feat): added global video/audio file format selection settings and other minor improvements --- src/App.tsx | 21 ++++++++++ src/pages/downloader.tsx | 18 +++++++- src/pages/settings.tsx | 88 ++++++++++++++++++++++++++++++++++++---- src/services/store.ts | 8 ++++ src/types/settings.ts | 3 ++ src/types/store.ts | 4 ++ 6 files changed, 131 insertions(+), 11 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index a2cdc56..e10dc16 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -57,6 +57,8 @@ export default function App({ children }: { children: React.ReactNode }) { const PREFER_VIDEO_OVER_PLAYLIST = useSettingsPageStatesStore(state => state.settings.prefer_video_over_playlist); const USE_PROXY = useSettingsPageStatesStore(state => state.settings.use_proxy); const PROXY_URL = useSettingsPageStatesStore(state => state.settings.proxy_url); + const VIDEO_FORMAT = useSettingsPageStatesStore(state => state.settings.video_format); + const AUDIO_FORMAT = useSettingsPageStatesStore(state => state.settings.audio_format); const appWindow = getCurrentWebviewWindow() const navigate = useNavigate(); @@ -144,6 +146,13 @@ export default function App({ children }: { children: React.ReactNode }) { console.log('Video Metadata:', videoMetadata); videoMetadata = isPlaylist ? videoMetadata.entries[0] : videoMetadata; + const fileType = determineFileType(videoMetadata.vcodec, videoMetadata.acodec); + + if (fileType !== 'unknown' && (VIDEO_FORMAT !== 'auto' || AUDIO_FORMAT !== 'auto')) { + if (VIDEO_FORMAT !== 'auto' && (fileType === 'video+audio' || fileType === 'video')) videoMetadata.ext = VIDEO_FORMAT; + if (AUDIO_FORMAT !== 'auto' && fileType === 'audio') videoMetadata.ext = AUDIO_FORMAT; + } + const videoId = resumeState?.video_id || generateVideoId(videoMetadata.id, videoMetadata.webpage_url_domain); const playlistId = isPlaylist ? (resumeState?.playlist_id || generateVideoId(videoMetadata.playlist_id, videoMetadata.webpage_url_domain)) : null; const downloadId = resumeState?.download_id || generateDownloadId(videoMetadata.id, videoMetadata.webpage_url_domain); @@ -173,6 +182,18 @@ export default function App({ children }: { children: React.ReactNode }) { args.push('--playlist-items', playlistIndex); } + if (fileType !== 'unknown' && (VIDEO_FORMAT !== 'auto' || AUDIO_FORMAT !== 'auto')) { + if (VIDEO_FORMAT !== 'auto' && fileType === 'video+audio') { + args.push('--merge-output-format', VIDEO_FORMAT); + } + if (VIDEO_FORMAT !== 'auto' && fileType === 'video') { + args.push('--remux-video', VIDEO_FORMAT); + } + if (AUDIO_FORMAT !== 'auto' && fileType === 'audio') { + args.push('--extract-audio', '--audio-format', AUDIO_FORMAT); + } + } + if (resumeState) { args.push('--continue'); } else { diff --git a/src/pages/downloader.tsx b/src/pages/downloader.tsx index 12300ea..65d8b3c 100644 --- a/src/pages/downloader.tsx +++ b/src/pages/downloader.tsx @@ -7,7 +7,7 @@ import { Input } from "@/components/ui/input"; import { Separator } from "@/components/ui/separator"; import { useToast } from "@/hooks/use-toast"; import { useAppContext } from "@/providers/appContextProvider"; -import { useCurrentVideoMetadataStore, useDownloaderPageStatesStore } from "@/services/store"; +import { useCurrentVideoMetadataStore, useDownloaderPageStatesStore, useSettingsPageStatesStore } from "@/services/store"; import { determineFileType, fileFormatFilter, formatBitrate, formatDurationString, formatFileSize, formatReleaseDate, formatYtStyleCount, isObjEmpty, sortByBitrate } from "@/utils"; import { Calendar, Clock, DownloadCloud, Eye, Info, Loader2, Music, ThumbsUp, Video, File, ListVideo, PackageSearch } from "lucide-react"; import { FormatSelectionGroup, FormatSelectionGroupItem } from "@/components/custom/formatSelectionGroup"; @@ -50,6 +50,9 @@ export default function DownloaderPage() { const setSelctedDownloadFormat = useDownloaderPageStatesStore((state) => state.setSelctedDownloadFormat); const setSelectedSubtitles = useDownloaderPageStatesStore((state) => state.setSelectedSubtitles); const setSelectedPlaylistVideoIndex = useDownloaderPageStatesStore((state) => state.setSelectedPlaylistVideoIndex); + + const videoFormat = useSettingsPageStatesStore(state => state.settings.video_format); + const audioFormat = useSettingsPageStatesStore(state => state.settings.audio_format); const audioOnlyFormats = videoMetadata?._type === 'video' ? sortByBitrate(videoMetadata?.formats.filter(fileFormatFilter('audio'))) : videoMetadata?._type === 'playlist' ? sortByBitrate(videoMetadata?.entries[Number(selectedPlaylistVideoIndex) - 1].formats.filter(fileFormatFilter('audio'))) : []; const videoOnlyFormats = videoMetadata?._type === 'video' ? sortByBitrate(videoMetadata?.formats.filter(fileFormatFilter('video'))) : videoMetadata?._type === 'playlist' ? sortByBitrate(videoMetadata?.entries[Number(selectedPlaylistVideoIndex) - 1].formats.filter(fileFormatFilter('video'))) : []; @@ -105,6 +108,17 @@ export default function DownloaderPage() { const containerRef = useRef(null); const bottomBarRef = useRef(null); + let selectedFormatExtensionMsg = 'Auto - unknown'; + if (selectedFormat?.ext) { + if ((selectedFormatFileType === 'video+audio' || selectedFormatFileType === 'video') && videoFormat !== 'auto') { + selectedFormatExtensionMsg = `Forced - ${videoFormat.toUpperCase()}`; + } else if (selectedFormatFileType === 'audio' && audioFormat !== 'auto') { + selectedFormatExtensionMsg = `Forced - ${audioFormat.toUpperCase()}`; + } else { + selectedFormatExtensionMsg = `Auto - ${selectedFormat.ext.toUpperCase()}`; + } + } + const searchForm = useForm>({ resolver: zodResolver(searchFormSchema), defaultValues: { @@ -596,7 +610,7 @@ export default function DownloaderPage() {
{videoMetadata._type === 'video' ? videoMetadata.title : videoMetadata._type === 'playlist' ? videoMetadata.entries[Number(selectedPlaylistVideoIndex) - 1].title : 'Unknown' } - {selectedFormat?.ext ? selectedFormat.ext.toUpperCase() : 'unknown'} ({selectedFormat?.resolution ? selectedFormat.resolution : 'unknown'}) {selectedFormat?.dynamic_range && selectedFormat.dynamic_range !== 'SDR' ? selectedFormat.dynamic_range : null } {selectedSubtitles.length > 0 ? `• ESUB` : null} • {selectedFormat?.filesize_approx ? formatFileSize(selectedFormat?.filesize_approx) : 'unknown filesize'} + {selectedFormatExtensionMsg} ({selectedFormat?.resolution ? selectedFormat.resolution : 'unknown'}) {selectedFormat?.dynamic_range && selectedFormat.dynamic_range !== 'SDR' ? selectedFormat.dynamic_range : null } {selectedSubtitles.length > 0 ? `• ESUB` : null} • {selectedFormat?.filesize_approx ? formatFileSize(selectedFormat?.filesize_approx) : 'unknown filesize'}