refactor: draw the src/scripts boundary, drop dead files

Make each directory answerable by path alone: src/ is what the Remotion build
compiles, scripts/ is what you run by hand.

Removed:
- `ffmpeg.sh` — never worked; every parameter was assigned `$1`, so bake/bypass
  were broken from the start. Superseded by `scripts/ffmpeg_tools.py bake|still`.
- `src/lrc2srt.ts` — the TypeScript port; `scripts/lrc2srt.py` is the script that
  was actually maintained, and it now handles the multi-timestamp cases the TS
  version did.
- `scripts/bom-gen.ts` — superseded by `scripts/bom_gen.py`.
- `scripts/ffmpegusage.txt` — legacy command notebook. Every recipe in it is now
  reproduced by `ffmpeg_tools.py`, including the `-map 0:v:0 -map 1:a:0 -c:v copy`
  mux and the FLAC `-compression_level 12` case, so it has no unique content left.

Also drops the `bom-gen` alias from the dispatcher (dash-case was TypeScript
naming) and documents the boundary in README.md and REMOTION-QUICKSTART.md.

`npm run lint` (eslint src && tsc) passes with src/ reduced to Remotion input.
This commit is contained in:
2026-09-10 18:18:04 +09:00
parent a1fbd64f87
commit afe397da3f
8 changed files with 31 additions and 296 deletions
+5 -4
View File
@@ -60,8 +60,8 @@ imported as a module. The dispatcher is a convenience, not a requirement.
## Hardware encoding
This machine is an **AMD Strix Halo** (Radeon 8060S). There is no NVIDIA card,
so the `nvenc` recipes in `ffmpegusage.txt` are reference only — they will not
run here. What does work is **VA-API** via the Mesa `radeonsi` driver:
so `nvenc` is unavailable here. What does work is **VA-API** via the Mesa
`radeonsi` driver:
| Codec | Encoder | Status |
| --- | --- | --- |
@@ -173,8 +173,9 @@ Notes on the choices baked in:
before it has fully downloaded.
For anything these do not cover, use `--dry-run` to print the generated command,
copy it, and edit it — the wrapper is a convenience, not a cage. The legacy
recipes this grew out of are preserved in `ffmpegusage.txt`.
copy it, and edit it — the wrapper is a convenience, not a cage. `hwprobe.py`
reports what this host can actually encode, so you can tell at a glance whether a
recipe will need a hardware-specific encoder.
---
-102
View File
@@ -1,102 +0,0 @@
#!/usr/bin/env node
// BOM generator — walks asset directories, lists files, prompts for descriptions, outputs BOM.yaml
//
// Usage:
// npx tsx scripts/bom-gen.ts [asset-root]
//
// Expected directory structure:
// audio/ — audio files
// images/ — image files
// fonts/ — font files
// videos/ — material video clips
//
// Output: BOM.yaml (YAML frontmatter-style)
import { readdirSync, statSync, writeFileSync } from "node:fs";
import { resolve, relative, join } from "node:path";
import { createInterface } from "node:readline";
type Asset = { path: string; size: number; description: string };
const ASSET_DIRS = ["audio", "images", "fonts", "videos"];
function walk(dir: string): Asset[] {
const assets: Asset[] = [];
for (const entry of readdirSync(dir, { withFileTypes: true })) {
const full = resolve(dir, entry.name);
if (entry.isDirectory()) {
assets.push(...walk(full));
} else {
assets.push({
path: relative(".", full),
size: statSync(full).size,
description: "",
});
}
}
return assets;
}
function humanSize(bytes: number): string {
const units = ["B", "KB", "MB", "GB"];
let i = 0;
while (bytes >= 1024 && i < units.length - 1) {
bytes /= 1024;
i++;
}
return `${bytes.toFixed(1)} ${units[i]}`;
}
async function main() {
const root = process.argv[2] || ".";
const rl = createInterface({ input: process.stdin, output: process.stdout });
console.log("BOM Generator");
console.log("=============\n");
let all: Asset[] = [];
for (const dir of ASSET_DIRS) {
const full = resolve(root, dir);
try {
const assets = walk(full);
all.push(...assets);
console.log(` ${dir}/ — ${assets.length} file(s)`);
} catch {
console.log(` ${dir}/ — not found (skipped)`);
}
}
if (all.length === 0) {
console.log("\nNo assets found. Nothing to do.\n");
rl.close();
return;
}
const totalSize = all.reduce((s, a) => s + a.size, 0);
console.log(`\nTotal: ${all.length} file(s), ${humanSize(totalSize)}\n`);
for (let i = 0; i < all.length; i++) {
const a = all[i];
console.log(`[${i + 1}/${all.length}] ${a.path} (${humanSize(a.size)})`);
a.description = (await new Promise<string>((r) =>
rl.question(" Description: ", r)
)).trim();
}
// Build YAML manually (no dependency)
let yaml = "---\nbom:\n";
for (const a of all) {
const desc = a.description.replace(/"/g, '\\"');
yaml += ` ${a.path}:\n description: "${desc}"\n`;
}
yaml += `total_files: ${all.length}\ntotal_size: ${totalSize}\n...`;
const bomPath = resolve(root, "BOM.yaml");
writeFileSync(bomPath, yaml);
console.log(`\n✓ Written to ${relative(root, bomPath)}\n`);
rl.close();
}
main().catch(console.error);
-28
View File
@@ -1,28 +0,0 @@
ffmpeg -hwaccel cuda -i pulse_raw_aac.mp4 -vf "ass=pulse.ass" -acodec copy pulse_sub_aac.mp4
ffmpeg -hwaccel cuda -i pulse_raw_flac.mkv -vf "ass=pulse.ass" -c:v h264_nvenc -acodec copy pulse_sub_flac.mkv
ffmpeg -hwaccel cuda -loop 1 -i pulse.png -i pulse.wav -c:v h264_nvenc -r 60 -c:a flac -compression_level 12 -pix_fmt yuv420p -shortest pulse.mkv
ffmpeg -hwaccel cuda -loop 1 -i pulse.png -i pulse_192.mp3 -c:v h264_nvenc -r 60 -c:a aac -b:a 320k -pix_fmt yuv420p -shortest pulse.mp4
Get-ChildItem -Filter *.mp4 | ForEach-Object {
$name = $_.BaseName
& 'ffmpeg' -i "$name.mp4" -vn -ar 44100 -ac 2 -b:a 320k "$name.mp3"
}
ffmpeg -i input_video.mp4 -vn -ar 44100 -ac 2 -q:a 0 -b:a 320k output_audio.mp3
# --- Pulse PV: mux real audio into the Remotion render (no video re-encode) ---
# pulse-pv-project/out/pulseraw.mp4 is video-only; copy its video stream as-is
# and add pulse.wav. -c:v copy = instant + lossless. Feeds the ass=... step.
# AAC (mp4), 320k:
ffmpeg -i pulse_raw.mp4 -i pulse.wav -map 0:v:0 -map 1:a:0 -c:v copy -c:a aac -b:a 320k -shortest pulse_raw_aac.mp4
# FLAC (mkv):
ffmpeg -i pulse_raw.mp4 -i pulse.wav -map 0:v:0 -map 1:a:0 -c:v copy -c:a flac -compression_level 12 -shortest pulse_raw_flac.mkv
-1
View File
@@ -35,7 +35,6 @@ ALIASES = {
"ffmpeg_tools": "ffmpeg",
"ffmpeg-tools": "ffmpeg",
"bom_gen": "bom",
"bom-gen": "bom",
"lrc": "lrc2srt",
"srt": "srt2ass",
}