❯ AI · Creator · 2025
Ark-Mask
A mobile-first platform that turns written stories into faceless AI videos for creators, with a multi-stage AI pipeline and credit-based freemium billing.
The problem
Faceless video is one of the biggest creator categories on YouTube, TikTok, and Reels, but producing it means moving a script through image prompts, storyboards, scene renders, voice, and a final merge — each step a different tool, each export a manual chore. Creators needed the pipeline as a single product: paste a story, get a video.
The approach
The decision that shaped everything: the story is the input and the finished video is the output, and the expensive, slow parts of that pipeline run server-side while the app owns the authoring experience. The pipeline is explicit — story → asset extraction → image prompts → reference images → storyboards → audio-included scene videos → cloud-merged final export — and every stage is an async job, not a blocking call. A unified provider abstraction makes Google Gemini and BytePlus Ark interchangeable, with BYOK keys forwarded in flight and never stored server-side.
Architecture
- Flutter App
- Cloud Firestore
- AI Story Pipeline
- Cloud Tasks + Cloud Run
- Gemini / BytePlus Ark
- GCS Media Store
- Stripe Credits
FLOWS
- Flutter Appoffline syncCloud Firestore
- Flutter AppstoryAI Story Pipeline
- AI Story PipelineenqueueCloud Tasks + Cloud Run
- Cloud Tasks + Cloud RungenerateGemini / BytePlus Ark
- Cloud Tasks + Cloud RunpersistCloud Firestore
- Cloud Tasks + Cloud RunmediaGCS Media Store
- GCS Media Storepresigned URLFlutter App
- Flutter ApppurchaseStripe Credits
The Flutter app (BLoC, GoRouter, Hive) gives creators an Obsidian-style project file browser and MDX editors, with offline editing via Firestore's offline persistence — writes queue locally and sync when connectivity returns, and real-time listeners update the UI as jobs progress. Generation workers (image, video, cloud-side FFmpeg merge) run on Cloud Tasks and Cloud Run, and FCM push closes the loop when a job finishes, so a minutes-long render never holds a request open.
Firestore is the unified content and operational store — projects, job state, and keys all in one place behind security rules, with an O(1) hashed-platform-key lookup for creator keys. Permanent media lives in GCS and is served through 1-hour-TTL presigned URLs, so an exported video's address expires long before a device could leak a permanent asset.
Billing is credit-based freemium — Free, Creator ($9/mo), Studio ($29/mo) — on Stripe. Credit debits and generation start race inside atomic Firestore transactions, which is what makes "charged but nothing rendered" a refund path rather than a support ticket; provider failures refund automatically.
Security gets its own pass: bcrypt-hashed platform API keys, hardware-backed secure storage on Keychain/Keystore, scoped GCS path authorization, TLS everywhere, and GDPR-compliant deletion.
Key decisions
BYOK model keys, in flight only
Creators bring their own keys and the platform never stores them; the abstraction layer also means one provider going down is a fallback, not an outage.
Server-side merge, nothing on device
The in-app timeline editor handles per-clip trim and cut/fade/dissolve transitions, but the FFmpeg merge is a Cloud Run job. Media never lives on the device, so storage stays small and a lost phone leaks nothing.
Firestore as the one store
Content, job state, and billing in a single document store with security rules beats a content database plus a queue plus a status table. The cost is discipline about query patterns and document size.
Atomic credits
Billing and generation race in Firestore transactions, not optimistic UI.
What I'd do differently
The offline sync layer was bolted on after the first online-only pass; starting with Firestore's offline persistence as the architecture, not the fallback, would have simplified a lot of edge-case handling. The security items — scoped GCS paths, hardware-backed key storage, GDPR deletion — shipped as a hardening pass rather than in the first design, and retrofitting scoped storage paths after real projects existed was the fiddliest part.