Create VX1 .pls for bpev.me/blog/vx1 sessions
0
create_pls.ts
51 lines 1.4 kB view raw
1import titleCase from "https://deno.land/x/case@2.1.1/titleCase.ts"; 2 3const [dir, postDir] = Deno.args; 4 5const contents = []; 6 7for await (const file of Deno.readDir(dir)) { 8 if (file.name[0] === ".") continue; 9 contents.push(file); 10} 11 12const filenames = contents 13 .map((dir) => dir.name) 14 .sort() 15 .reverse(); 16 17const entriesAsync = filenames.map(formatEntry); 18const entries = await Promise.all(entriesAsync); 19 20const plsText = `[playlist] 21${entries.join("\n")} 22NumberOfEntries=${entries.length} 23Version=2 24`; 25 26console.log(plsText); 27 28async function formatEntry(fileName, index) { 29 const num = index + 1; 30 const [nameOrDate, memoName] = fileName.split("_"); 31 const title = memoName 32 ? titleCase(memoName.split(".")[0]) + ` (${nameOrDate})` 33 : titleCase(nameOrDate.split(".")[0]); 34 35 return "" + 36 `File${num}=https://static.bpev.me/blog/${postDir}/version/${fileName}\n` + 37 `Title${num}=${title}\n` + 38 `Length${num}=${await getDurationSeconds(fileName)}\n`; 39} 40 41async function getDurationSeconds(fileName) { 42 const p = Deno.run({ 43 cmd: [ "/Users/ben/apps/ffmpeg", "-i", fileName ], 44 stderr: "piped", 45 }); 46 await p.status(); 47 const output = new TextDecoder().decode(await p.stderrOutput()); 48 const time = output.match(/Duration: ([^.]*)/)[1]; 49 const [hours, minutes, seconds] = time.split(":"); 50 return (parseInt(hours) * 3600) + (parseInt(minutes) * 60) + parseInt(seconds); 51}