Monorepo for Aesthetic.Computer
aesthetic.computer
Tape MP4 Conversion - Success Report#
Summary#
Successfully implemented and tested MP4 video conversion for aesthetic.computer tapes with ATProto blob uploads.
Problem Solved#
H.264 encoding requires video dimensions divisible by 2. Many tapes have odd-width canvases (e.g., 337x160).
Solution#
Added ffmpeg scale filter: scale=trunc(iw/2)*2:trunc(ih/2)*2
- Rounds down to nearest even number
- Preserves aspect ratio
- Minimal quality impact (1px maximum width/height adjustment)
Test Results#
Date: 2025-01-25 Test Set: 32 anonymous tapes from art.at.aesthetic.computer
Metrics#
- ✅ 100% success rate (32/32 conversions)
- ✅ MP4 sizes: 27.71 KB - 439.04 KB (average ~180 KB)
- ✅ Frame rate: 60 fps (calculated from timing.json)
- ✅ Codec: H.264 with yuv420p pixel format
- ✅ Optimization: faststart flag enabled for web streaming
- ✅ All blobs uploaded to ATProto successfully
- ✅ All MongoDB records updated with rkeys
Sample Conversions#
| Tape Code | ZIP Size | MP4 Size | Dimensions |
|---|---|---|---|
| 9Yo | Unknown | 108.89 KB | 640x480 (even) |
| eKZ | Unknown | 343.71 KB | 337x176 → 336x176 |
| 3Pt | Unknown | 27.71 KB | Small tape |
| oSm | Unknown | 439.04 KB | Longest tape |
Implementation Details#
ffmpeg Arguments#
-r 60 # Frame rate (from timing.json)
-i /tmp/tape-xxx/frame-%05d.png # Input frames (5-digit padded)
-vf scale=trunc(iw/2)*2:trunc(ih/2)*2 # Ensure even dimensions
-c:v libx264 # H.264 codec
-pix_fmt yuv420p # Compatible pixel format
-movflags +faststart # Web streaming optimization
-y output.mp4 # Overwrite output
Error Handling#
- Falls back to no blob if conversion fails
- Record still created with zipUrl and acUrl
- Cleanup of temp directories guaranteed
Files Modified#
-
tape-to-mp4.mjs (line 92)
- Added scale filter to ffmpeg arguments
-
media-atproto.mjs (lines 167-215)
- TAPE buildRecord with MP4 conversion
- Dynamic import of tape-to-mp4.mjs
- Blob upload logic
-
sync-atproto.mjs
- Added --tapes-only flag
- Anonymous content support
Next Steps#
- ✅ Test complete - all 32 anonymous tapes synced
- 🔄 Sync Jeffrey's content (~3,000 items)
- 🔄 Deploy to production
- 🔄 Full sync of 4,201 users
Performance Notes#
- Conversion time: ~3-5 seconds per tape
- Batch size: 10 concurrent conversions
- Total time for 32 tapes: ~2 minutes
- No rate limiting issues with ATProto blob uploads
Storage Impact#
- Average MP4 size: ~180 KB
- 32 tapes: ~5.76 MB total
- Extrapolated for all users: Estimated 50-100 MB (assuming ~300-500 tapes total)
Conclusion#
MP4 conversion implementation is production-ready ✅