Uses ffmpeg to generate an H.264/AAC video from an MP3 file with a centred title overlay. Supports optional background image (title at bottom) or solid colour (title centred). Includes spec, dryrun support, and 10 tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
100 lines
3.5 KiB
Markdown
100 lines
3.5 KiB
Markdown
# mp3-to-mp4
|
|
|
|
## Purpose
|
|
|
|
Convert an MP3 audio file into an MP4 video that displays a static title card, suitable for uploading to video platforms.
|
|
|
|
## Dependencies
|
|
|
|
- `ffmpeg` (6.x+) — video/audio encoding
|
|
|
|
## Usage
|
|
|
|
```
|
|
mp3-to-mp4 [OPTIONS] <input.mp3>
|
|
```
|
|
|
|
### Arguments
|
|
|
|
| Argument | Description |
|
|
|---|---|
|
|
| `<input.mp3>` | Path to the MP3 file to convert (required) |
|
|
|
|
### Options
|
|
|
|
| Flag | Description |
|
|
|---|---|
|
|
| `--title`, `-t` | Title text to display on the video (required) |
|
|
| `--output`, `-o` | Output file path (default: same name as input with `.mp4` extension) |
|
|
| `--resolution`, `-r` | Video resolution as WxH (default: `1920x1080`) |
|
|
| `--font-size` | Font size in pixels (default: `72`) |
|
|
| `--font-color` | Font colour (default: `white`) |
|
|
| `--bg-color` | Background colour (default: `black`; ignored when `--image` is set) |
|
|
| `--image`, `-i` | Background image path (optional; scaled to fill the resolution) |
|
|
| `--dryrun`, `-n` | Preview what would happen without creating files |
|
|
| `--help`, `-h` | Show usage information |
|
|
|
|
## Behaviour
|
|
|
|
1. **Validate inputs.** Check that `<input.mp3>` exists and is readable. Check that `ffmpeg` is on PATH. Check that `--title` is provided. Exit 1 with a clear message if any check fails.
|
|
|
|
2. **Determine duration.** Use `ffprobe` to get the audio duration in seconds.
|
|
|
|
3. **Generate video.** Use ffmpeg to:
|
|
- **Without `--image`:** Create a solid colour background at the specified resolution for the audio duration. Title is centred both horizontally and vertically.
|
|
- **With `--image`:** Scale the image to fill the resolution (crop to fit). Title is centred horizontally near the bottom of the frame.
|
|
- Mux the MP3 audio as the audio stream
|
|
- Encode with H.264 video and AAC audio for broad compatibility
|
|
- Use `-shortest` to match video duration to audio duration
|
|
|
|
4. **Report.** Print the output path on success.
|
|
|
|
## Dryrun Behaviour
|
|
|
|
When `--dryrun` / `-n` is passed:
|
|
|
|
```
|
|
[dryrun] Input: /path/to/episode.mp3
|
|
[dryrun] Output: /path/to/episode.mp4
|
|
[dryrun] Title: My Podcast Episode
|
|
[dryrun] Duration: 3m 42s
|
|
[dryrun] Resolution: 1920x1080
|
|
[dryrun] Font size: 72
|
|
[dryrun] Font color: white
|
|
[dryrun] Background: black (or image path when --image is used)
|
|
[dryrun] Dependencies OK: ffmpeg 6.1.1
|
|
[dryrun] Would generate .mp4 video file
|
|
```
|
|
|
|
No files are created or modified.
|
|
|
|
## Edge Cases
|
|
|
|
- **Input file not found:** Exit 1 with `Error: file not found: <path>`
|
|
- **ffmpeg not installed:** Exit 1 with `Error: ffmpeg not found. Install with: sudo apt install ffmpeg`
|
|
- **--title not provided:** Exit 1 with `Error: --title is required`
|
|
- **Output file already exists:** Overwrite without prompting (standard pipeline behaviour)
|
|
- **Title text is very long:** ffmpeg's drawtext wraps naturally; no special handling needed
|
|
- **Input is not a valid audio file:** ffprobe will fail; exit 1 with `Error: could not read audio duration from: <path>`
|
|
- **--image file not found:** Exit 1 with `Error: image not found: <path>`
|
|
- **--image with --bg-color:** `--bg-color` is silently ignored when `--image` is provided
|
|
|
|
## Examples
|
|
|
|
```bash
|
|
# Basic conversion
|
|
mp3-to-mp4 -t "My Podcast Episode" episode.mp3
|
|
|
|
# Custom output and resolution
|
|
mp3-to-mp4 -t "Talk Title" -o talk.mp4 -r 1280x720 recording.mp3
|
|
|
|
# Custom styling
|
|
mp3-to-mp4 -t "Keynote" --font-size 96 --font-color yellow --bg-color "#1a1a2e" speech.mp3
|
|
|
|
# With a background image (title at bottom)
|
|
mp3-to-mp4 -t "Keynote 2026" -i cover.jpg recording.mp3
|
|
|
|
# Preview without creating files
|
|
mp3-to-mp4 --dryrun -t "Test" audio.mp3
|
|
```
|