Options (quality, subtitles) are now derived from a yt-dlp -J probe of the submitted URL instead of a static list, so users can't pick combinations the source video doesn't actually support. Submission is blocked until the probe succeeds. - New /api/probe endpoint + src/lib/ytdlp-probe.ts, with its own rate limiter (rate-limit.ts refactored into a createRateLimiter factory). - New options: subtitle language selection, clip start/end trim, MP3 audio quality. - Fixed buildYtdlpArgs: format=mp3 never triggered audio extraction (-x/--audio-format), and quality=best never applied --merge-output-format, so the chosen container had no real effect. - Cross-platform yt-dlp invocation: the bundled bin/yt-dlp is a Python zipapp relying on a shebang, which Windows' spawn() can't run directly. buildYtdlpCommand() runs it through `python` on Windows and execs it directly on Linux/o2switch, where the shebang works natively. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
const mockExistsSync = jest.fn()
|
|
jest.mock('fs', () => ({ existsSync: (...args: unknown[]) => mockExistsSync(...args) }))
|
|
|
|
import { buildYtdlpCommand } from '../ytdlp'
|
|
|
|
function setPlatform(platform: NodeJS.Platform) {
|
|
Object.defineProperty(process, 'platform', { value: platform })
|
|
}
|
|
|
|
describe('buildYtdlpCommand', () => {
|
|
const originalPlatform = process.platform
|
|
|
|
afterEach(() => {
|
|
setPlatform(originalPlatform)
|
|
mockExistsSync.mockReset()
|
|
})
|
|
|
|
it('runs the bundled binary directly on Linux', () => {
|
|
setPlatform('linux')
|
|
mockExistsSync.mockReturnValue(true)
|
|
const { command, args } = buildYtdlpCommand(['-J', 'https://x.test'])
|
|
expect(command).toContain('yt-dlp')
|
|
expect(args).toEqual(['-J', 'https://x.test'])
|
|
})
|
|
|
|
it('runs the bundled binary through python on Windows', () => {
|
|
setPlatform('win32')
|
|
mockExistsSync.mockReturnValue(true)
|
|
const { command, args } = buildYtdlpCommand(['-J', 'https://x.test'])
|
|
expect(command).toBe('python')
|
|
expect(args[0]).toContain('yt-dlp')
|
|
expect(args.slice(1)).toEqual(['-J', 'https://x.test'])
|
|
})
|
|
|
|
it('runs a system-wide yt-dlp directly on Windows when no bundled binary exists', () => {
|
|
setPlatform('win32')
|
|
mockExistsSync.mockReturnValue(false)
|
|
const { command, args } = buildYtdlpCommand(['-J', 'https://x.test'])
|
|
expect(command).toBe('yt-dlp')
|
|
expect(args).toEqual(['-J', 'https://x.test'])
|
|
})
|
|
|
|
it('runs a system-wide yt-dlp directly on Linux when no bundled binary exists', () => {
|
|
setPlatform('linux')
|
|
mockExistsSync.mockReturnValue(false)
|
|
const { command, args } = buildYtdlpCommand(['-J', 'https://x.test'])
|
|
expect(command).toBe('yt-dlp')
|
|
expect(args).toEqual(['-J', 'https://x.test'])
|
|
})
|
|
})
|