What does simreel do?
Record the user's real app in the iOS Simulator and cut it into two files:
reel-1080x1920.mp4: the recording inside a phone body on a gradient, one caption per scene, an end card. For X, Reels, TikTok, Product Hunt.appstore-preview-886x1920.mp4: the plain recording, sized and encoded for App Store Connect.
Everything runs locally with Xcode and ffmpeg. No accounts, no paid APIs.
Rules
- Show only what the app really does. Captions describe what is on screen; never add claims, numbers or reviews the footage does not show.
- Keep private data out of frame. Use a fresh simulator or demo data, and look at the frames before delivering.
- Touch only the simulator you were told to use. Other booted simulators may belong to someone else's work; never pass
bootedwhen more than one is running. - Decline tracking and cookie prompts while recording unless the user says otherwise.
Steps
- Find the simulator.
xcrun simctl list devices booted. If the app is not installed, build and install it with the user's own tooling. - Walk the app once without recording. Pick 3 to 5 moments that show the main features. Clear onboarding, permission and cookie dialogs now so they stay out of the take.
- Record one take.
Pause about a second on each screen you want to keep. If taps fail right after a simulator boots, wait 20 seconds and retry.scripts/record.sh start work/raw.mp4 <UDID> # drive the app: your simulator tool, an XCUITest in the project, or ask the user to tap through scripts/record.sh stop <UDID> - Read the take. The file ends at the last screen change, so a still final screen is cut off and a take of a screen that never changes is almost empty. Time scenes from the file, not from memory.
Openpython3 scripts/compose.py frames work/raw.mp4 workwork/contact-sheet.png: 8 tiles per row, tile N is second N. - Write
storyboard.json.{ "app_name": "MyApp", "background": ["#0B1020", "#3B2AA8"], "scenes": [ {"start": 0.3, "end": 5.8, "caption": "What this screen does"}, {"start": 8.0, "end": 10.0, "speed": 0.8, "caption": "Next step"} ], "end_card": {"title": "MyApp", "subtitle": "The app's own tagline"} }start/endare seconds in the recording.speedbelow 1 slows a scene, above 1 speeds it up.holdfreezes the scene's last frame for that many seconds, which is how you linger on a result screen.backgroundtakes one colour or a top-to-bottom gradient;text_colorandcaption_sizeare optional. Leaveend_cardout to end on the last scene. Cut out loading spinners. The scenes must add up to 15-30 seconds or App Store Connect rejects the preview. - Render.
It printspython3 scripts/compose.py render work/raw.mp4 storyboard.json outout/report.jsonand warns when the preview duration is out of range. - Check before you hand over. Pull a frame from each scene (
ffmpeg -ss <t> -i out/reel-1080x1920.mp4 -frames:v 1 f.png) and look at it: caption matches the screen, nothing private, nothing cut off.
Notes
- Requirements: macOS, Xcode (for
simctlandswift), ffmpeg, python3. record.shsets the status bar to 9:41 with full battery and signal. Clear it afterwards withxcrun simctl status_bar <UDID> clear.- App Store preview numbers used here (886x1920, 15-30 s, 30 fps, H.264 High 4.0, stereo AAC) come from Apple's app preview specifications. Check that page if an upload is rejected.
- The audio track is silent. Add music or voice in an editor if you want sound.