Restore the video branch in openPlayback

The screen share never started because openPlayback had no video branch
left: removing the old direct-URL seek path took it with it, since it sat
between the anchors used for that edit. canShowVideo and the pipeline
import stayed behind, and nothing failed to compile, so it looked wired
up while every track quietly took the audio-only path.

Verified end to end: openPlayback now returns a 640x360 track, format 18
is selected, and 12 seconds of playback yields 202 frames alongside the
audio.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Leonid Pershin
2026-09-09 02:09:11 +03:00
co-authored by Claude Opus 5
parent 0b166304c2
commit e06c42f60c
+16
View File
@@ -1,5 +1,6 @@
import type { Readable } from "node:stream"; import type { Readable } from "node:stream";
import { config } from "../config.js"; import { config } from "../config.js";
import { logger } from "../logger.js";
import { UserFacingError, type Requester, type SearchResult, type Track } from "../types.js"; import { UserFacingError, type Requester, type SearchResult, type Track } from "../types.js";
import * as direct from "./direct.js"; import * as direct from "./direct.js";
import * as local from "./local.js"; import * as local from "./local.js";
@@ -9,6 +10,8 @@ import * as ytdlp from "./ytdlp.js";
export { checkAvailable as checkYtDlp, checkCookies, checkProxy, describeProxy } from "./ytdlp.js"; export { checkAvailable as checkYtDlp, checkCookies, checkProxy, describeProxy } from "./ytdlp.js";
export { isEnabled as isLocalLibraryEnabled, listFiles as listLocalFiles } from "./local.js"; export { isEnabled as isLocalLibraryEnabled, listFiles as listLocalFiles } from "./local.js";
const log = logger.child({ mod: "sources" });
const YOUTUBE_HOSTS = ["youtube.com", "youtu.be", "music.youtube.com", "m.youtube.com"]; const YOUTUBE_HOSTS = ["youtube.com", "youtu.be", "music.youtube.com", "m.youtube.com"];
const SOUNDCLOUD_HOSTS = ["soundcloud.com", "on.soundcloud.com", "m.soundcloud.com"]; const SOUNDCLOUD_HOSTS = ["soundcloud.com", "on.soundcloud.com", "m.soundcloud.com"];
@@ -209,6 +212,19 @@ export async function openPlayback(track: Track, seekSeconds = 0): Promise<Playb
}; };
} }
// The format is checked before committing to the video pipeline: audio comes
// out of that same pipeline, so falling back afterwards would kill the sound.
if (canShowVideo(track) && (await ytdlp.hasProgressiveVideo(track.url, config.VIDEO_HEIGHT))) {
log.info({ title: track.title }, "playing with video");
const pipeline = openVideoPipeline(track.url, seekSeconds);
return {
input: pipeline.audio,
inputOptions: pipeline.audioInputOptions,
cleanup: () => pipeline.kill(),
video: { stream: pipeline.video, width: pipeline.width, height: pipeline.height },
};
}
// Everything goes through yt-dlp: YouTube stalls direct CDN URLs fetched by // Everything goes through yt-dlp: YouTube stalls direct CDN URLs fetched by
// anything else, and ffmpeg would bypass a SOCKS proxy anyway. Seeking // anything else, and ffmpeg would bypass a SOCKS proxy anyway. Seeking
// therefore costs a decode up to the offset instead of an HTTP range request. // therefore costs a decode up to the offset instead of an HTTP range request.