Monorepo for Aesthetic.Computer
aesthetic.computer
1# Tape MP4 Conversion - Success Report
2
3## Summary
4Successfully implemented and tested MP4 video conversion for aesthetic.computer tapes with ATProto blob uploads.
5
6## Problem Solved
7H.264 encoding requires video dimensions divisible by 2. Many tapes have odd-width canvases (e.g., 337x160).
8
9## Solution
10Added ffmpeg scale filter: `scale=trunc(iw/2)*2:trunc(ih/2)*2`
11- Rounds down to nearest even number
12- Preserves aspect ratio
13- Minimal quality impact (1px maximum width/height adjustment)
14
15## Test Results
16**Date:** 2025-01-25
17**Test Set:** 32 anonymous tapes from art.at.aesthetic.computer
18
19### Metrics
20- ✅ **100% success rate** (32/32 conversions)
21- ✅ **MP4 sizes:** 27.71 KB - 439.04 KB (average ~180 KB)
22- ✅ **Frame rate:** 60 fps (calculated from timing.json)
23- ✅ **Codec:** H.264 with yuv420p pixel format
24- ✅ **Optimization:** faststart flag enabled for web streaming
25- ✅ **All blobs uploaded** to ATProto successfully
26- ✅ **All MongoDB records** updated with rkeys
27
28### Sample Conversions
29| Tape Code | ZIP Size | MP4 Size | Dimensions |
30|-----------|----------|----------|------------|
31| 9Yo | Unknown | 108.89 KB | 640x480 (even) |
32| eKZ | Unknown | 343.71 KB | 337x176 → 336x176 |
33| 3Pt | Unknown | 27.71 KB | Small tape |
34| oSm | Unknown | 439.04 KB | Longest tape |
35
36## Implementation Details
37
38### ffmpeg Arguments
39```bash
40-r 60 # Frame rate (from timing.json)
41-i /tmp/tape-xxx/frame-%05d.png # Input frames (5-digit padded)
42-vf scale=trunc(iw/2)*2:trunc(ih/2)*2 # Ensure even dimensions
43-c:v libx264 # H.264 codec
44-pix_fmt yuv420p # Compatible pixel format
45-movflags +faststart # Web streaming optimization
46-y output.mp4 # Overwrite output
47```
48
49### Error Handling
50- Falls back to no blob if conversion fails
51- Record still created with zipUrl and acUrl
52- Cleanup of temp directories guaranteed
53
54## Files Modified
551. **tape-to-mp4.mjs** (line 92)
56 - Added scale filter to ffmpeg arguments
57
582. **media-atproto.mjs** (lines 167-215)
59 - TAPE buildRecord with MP4 conversion
60 - Dynamic import of tape-to-mp4.mjs
61 - Blob upload logic
62
633. **sync-atproto.mjs**
64 - Added --tapes-only flag
65 - Anonymous content support
66
67## Next Steps
681. ✅ Test complete - all 32 anonymous tapes synced
692. 🔄 Sync Jeffrey's content (~3,000 items)
703. 🔄 Deploy to production
714. 🔄 Full sync of 4,201 users
72
73## Performance Notes
74- Conversion time: ~3-5 seconds per tape
75- Batch size: 10 concurrent conversions
76- Total time for 32 tapes: ~2 minutes
77- No rate limiting issues with ATProto blob uploads
78
79## Storage Impact
80- Average MP4 size: ~180 KB
81- 32 tapes: ~5.76 MB total
82- Extrapolated for all users: Estimated 50-100 MB (assuming ~300-500 tapes total)
83
84## Conclusion
85MP4 conversion implementation is **production-ready** ✅