Generate lyric-synced vertical videos for Instagram Reels using NASA Landsat imagery.
- Downloads satellite imagery from NASA's Your Name In Landsat — each letter maps to a unique aerial photo.
- Uses OpenAI Whisper to transcribe any song with word-level timestamps.
- Stitches the Landsat images together with smooth crossfade transitions using MoviePy, synced exactly to the lyrics.
Requires Python 3.10+, FFmpeg, and uv/pip.
# Install dependencies
uv pip install -e .
# or: pip install -e .A convenience wrapper script ./nasa-word-song is provided. It automatically uses the virtual environment and sets up the correct paths. Use it instead of python -m nasa_word_song.
./nasa-word-song fetch "dalas" -o ./landsat_images./nasa-word-song generate song.mp3 -i ./landsat_images -o final_reel.mp4This will:
- Transcribe
song.mp3with Whisper - Map each sung word to its first letter's Landsat image
- Render a 1080x1920 (9:16) MP4 with crossfade transitions
If you keep all songs in one folder, pass the folder path as audio and pick a song with --song:
./nasa-word-song generate ./songs --song "track1.mp3" -i ./landsat_images -o reel.mp4To generate a video for only a specific segment (perfect for 20-30s Reels), use --start and --end:
./nasa-word-song generate ./songs --song "track1.mp3" --start 0:15 --end 0:45 -i ./landsat_images -o reel.mp4Timestamps accept seconds (15) or MM:SS (1:30).
| Command | Purpose |
|---|---|
fetch <word> |
Download Landsat images for every letter in <word> |
transcribe <audio> |
Save word-level timestamps to JSON |
generate <audio> |
Render the final Reels video |
audio— Path to audio file or a folder containing songs--song— Song filename (required whenaudiois a folder)-i, --images— Folder with Landsat images (required)-o, --output— Output MP4 path (default:final_reel.mp4)-t, --transcription— Use a pre-computed JSON instead of running Whisper-c, --crossfade— Transition duration in seconds (default:0.2)-f, --fallback— Image to show when a letter is missing--word-mode— Map full words instead of first letters-m, --model— Whisper model:tiny,base,small,medium,large--start— Start timestamp in seconds orMM:SS(e.g.15or0:15)--end— End timestamp in seconds orMM:SS(e.g.45or0:45)
# 1. Download images for a short phrase
./nasa-word-song fetch "dreams" -o ./landsat_images
# 2. Generate a 30-second clip from a songs folder
./nasa-word-song generate ./my_songs --song "dreams.mp3" --start 0:30 --end 1:00 -i ./landsat_images -o reel.mp4 --crossfade 0.15For much faster transcription on M1/M2/M3 Macs, install the optional dependency:
uv pip install -e ".[fast]"Then edit transcribe.py to use mlx_whisper instead of openai-whisper.