52 lines
1.3 KiB
TypeScript
52 lines
1.3 KiB
TypeScript
import { spawn } from "node:child_process";
|
|
|
|
export async function get_audio(url: string): Promise<string> {
|
|
const ytDlpBin = process.env.YT_DLP_BIN_PATH! ?? "yt-dlp";
|
|
const dataDir = "./data";
|
|
|
|
const idMatch = /[?&]v=([a-zA-Z0-9_-]{11})/.exec(url);
|
|
if (!idMatch) throw new Error("Cannot extract video ID");
|
|
|
|
const id = idMatch[1];
|
|
console.log(`ID: ${id}`);
|
|
|
|
// ---- run yt-dlp ----
|
|
await new Promise<void>((resolve, reject) => {
|
|
const p = spawn(ytDlpBin, [
|
|
"-x",
|
|
"--audio-format", "opus",
|
|
"--audio-quality", "0",
|
|
"--no-playlist",
|
|
"--paths", dataDir,
|
|
url,
|
|
]);
|
|
|
|
p.stderr.on("data", d => process.stderr.write(d));
|
|
p.on("close", code => code === 0 ? resolve() : reject(new Error("yt-dlp failed")));
|
|
});
|
|
|
|
// ---- find the file ----
|
|
return await new Promise<string>((resolve, reject) => {
|
|
const find = spawn("find", [
|
|
dataDir,
|
|
"-type", "f",
|
|
"-iname", `*${id}*.opus`,
|
|
"-exec", "readlink", "-f", "{}", ";",
|
|
]);
|
|
|
|
let out = "";
|
|
|
|
find.stdout.on("data", d => out += d.toString());
|
|
find.stderr.on("data", d => process.stderr.write(d));
|
|
|
|
find.on("close", code => {
|
|
if (code !== 0 || !out.trim()) {
|
|
reject(new Error("Audio file not found"));
|
|
} else {
|
|
resolve(out.trim());
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|