feat(downloads): guarantee every download is browser-playable (mp4/H.264/AAC)
The Download module's purpose is download -> share -> play in-browser, so the output must play in EVERY browser (iOS/Safari/WebKit included). The only universally-safe combo is mp4 + H.264 + AAC/MP3. - formats.normalize() now CLAMPS every spec to that profile (container->mp4, vcodec->None, audio_format opus->m4a) at the single point all paths flow through (picker, stored profile, raw API) — not just by hiding UI options. A source exposing no H.264 is still caught by the worker's browser-safe re-encode, so playability is guaranteed end-to-end. - build_ydl_opts drops the now-unreachable non-compat branches (+ _VCODEC_SORT). - _SIG_VERSION 3->4 so assets cached under an old non-compat spec — or a stale non-H.264 mp4 that slipped the v3 net (the HEVC Facebook dls) — re-derive. - ProfileEditor drops the container/codec pickers and Opus; audio is M4A/MP3. - i18n: remove the now-unused container/vcodec/any keys (HU+EN parity).
This commit is contained in:
@@ -195,6 +195,8 @@ export default function ProfileEditor({ onClose }: { onClose: () => void }) {
|
||||
<label className="block text-sm font-medium mb-1">
|
||||
{t("downloads.profiles.audioFormat")}
|
||||
</label>
|
||||
{/* Only browser-playable audio: AAC (m4a) + MP3. Opus is dropped — Safari plays it
|
||||
unreliably as a bare file, and the module's purpose is in-browser playback. */}
|
||||
<select
|
||||
value={spec.audio_format ?? "m4a"}
|
||||
onChange={set("audio_format")}
|
||||
@@ -202,39 +204,12 @@ export default function ProfileEditor({ onClose }: { onClose: () => void }) {
|
||||
>
|
||||
<option value="m4a">M4A</option>
|
||||
<option value="mp3">MP3</option>
|
||||
<option value="opus">Opus</option>
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
{spec.mode !== "a" && (
|
||||
<>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">
|
||||
{t("downloads.profiles.container")}
|
||||
</label>
|
||||
<select
|
||||
value={spec.container ?? "mp4"}
|
||||
onChange={set("container")}
|
||||
className={inputCls}
|
||||
>
|
||||
<option value="mp4">MP4</option>
|
||||
<option value="mkv">MKV</option>
|
||||
<option value="webm">WebM</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">
|
||||
{t("downloads.profiles.vcodec")}
|
||||
</label>
|
||||
<select value={spec.vcodec ?? ""} onChange={set("vcodec")} className={inputCls}>
|
||||
<option value="">{t("downloads.profiles.any")}</option>
|
||||
<option value="h264">H.264</option>
|
||||
<option value="vp9">VP9</option>
|
||||
<option value="av1">AV1</option>
|
||||
</select>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{/* Container/codec are no longer user-selectable: every download is clamped to the
|
||||
mp4/H.264/AAC compat profile (the only universally browser-playable combo) so a
|
||||
shared link plays everywhere, iOS/Safari included. Enforced in backend `normalize`. */}
|
||||
</div>
|
||||
<div className="space-y-1.5 pt-1">
|
||||
{spec.mode !== "a" && (
|
||||
|
||||
@@ -151,10 +151,7 @@
|
||||
"modeA": "Audio only",
|
||||
"quality": "Max quality",
|
||||
"best": "Best",
|
||||
"container": "Container",
|
||||
"audioFormat": "Audio format",
|
||||
"vcodec": "Video codec",
|
||||
"any": "Any",
|
||||
"embedSubs": "Embed subtitles",
|
||||
"embedChapters": "Embed chapters",
|
||||
"embedThumbnail": "Embed thumbnail",
|
||||
|
||||
@@ -151,10 +151,7 @@
|
||||
"modeA": "Csak hang",
|
||||
"quality": "Max. minőség",
|
||||
"best": "Legjobb",
|
||||
"container": "Konténer",
|
||||
"audioFormat": "Hangformátum",
|
||||
"vcodec": "Videó codec",
|
||||
"any": "Bármelyik",
|
||||
"embedSubs": "Feliratok beágyazása",
|
||||
"embedChapters": "Fejezetek beágyazása",
|
||||
"embedThumbnail": "Bélyegkép beágyazása",
|
||||
|
||||
Reference in New Issue
Block a user