feat: subtitles while streaming, and fetched when a download lacks them
YouTube's HLS manifest carries a dozen audio renditions and no subtitles whatsoever — checked against a live master playlist: 16 EXT-X-MEDIA entries, all TYPE=AUDIO, zero SUBTITLES. So the track menu could only ever list audio while streaming, which is what it did. Subtitles are now fetched separately with yt-dlp, tidied through the existing VTT cleanup, and cached per video and language. They reach the player as blob URLs, which share the document's origin — a file:// or 127.0.0.1 track would be cross-origin to the page and need CORS the media pipeline cannot supply. The same path fills in a download saved before subtitles were switched on, without fetching the video again. YouTube serves identical auto-generated captions under both "en" and "en-orig", so byte-identical texts collapse to one entry rather than offering the same track twice, and tracks are labelled "English" rather than "en". The subtitle preference now defaults to English. "None" is a poor default for a setting whose whole purpose is captions: it silently means no subtitles are downloaded, fetched, or offered anywhere, and the Settings text now says so.
This commit is contained in:
+4
-3
@@ -16,7 +16,8 @@ import { useDownloads } from "./hooks/useDownloads";
|
||||
import { useFeed } from "./hooks/useFeed";
|
||||
import { useWindowFullscreen } from "./hooks/useWindowFullscreen";
|
||||
import {
|
||||
BULK_LIMITS, DEFAULT_BULK_LIMIT, QUALITIES, STREAM_QUALITIES, SUB_LANGS,
|
||||
BULK_LIMITS, DEFAULT_BULK_LIMIT, DEFAULT_SUB_LANG,
|
||||
QUALITIES, STREAM_QUALITIES, SUB_LANGS,
|
||||
type FeedFilter, type FeedItem, type Quality, type RefreshProgress,
|
||||
} from "./types";
|
||||
|
||||
@@ -66,9 +67,9 @@ export default function App() {
|
||||
const [subLang, setSubLang] = useState(() => {
|
||||
try {
|
||||
const stored = localStorage.getItem("flighttube.subLang");
|
||||
return SUB_LANGS.some((l) => l.value === stored) ? stored! : "off";
|
||||
return SUB_LANGS.some((l) => l.value === stored) ? stored! : DEFAULT_SUB_LANG;
|
||||
} catch {
|
||||
return "off";
|
||||
return DEFAULT_SUB_LANG;
|
||||
}
|
||||
});
|
||||
const [streamQuality, setStreamQuality] = useState<Quality>(() => {
|
||||
|
||||
Reference in New Issue
Block a user