Monorepo for Aesthetic.Computer aesthetic.computer
core system backend TAPE-MP4-SUCCESS.md
2.9 kB

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 #

  1. tape-to-mp4.mjs (line 92)

    • Added scale filter to ffmpeg arguments
  2. media-atproto.mjs (lines 167-215)

    • TAPE buildRecord with MP4 conversion
    • Dynamic import of tape-to-mp4.mjs
    • Blob upload logic
  3. sync-atproto.mjs

    • Added --tapes-only flag
    • Anonymous content support

Next Steps #

  1. ✅ Test complete - all 32 anonymous tapes synced
  2. 🔄 Sync Jeffrey's content (~3,000 items)
  3. 🔄 Deploy to production
  4. 🔄 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 ✅