Here's the full "About the project" content to paste in:


Inspiration

Real estate agents spend hours every week producing listing content — staging consultations, professional photography, video editing, voiceover recording, social copywriting. Each step is manual, disconnected, and expensive. Small agencies simply can't afford it per listing.

We asked: what if a single room photo could trigger an entire content pipeline autonomously? Not a template. Not a crop-and-caption tool. A genuine multi-agent system where each AI stage produces typed, structured output consumed by the next — the same way a real production team hands off work.


What it does

RoomReel takes one room photo and runs it through a pipeline of 8 specialised AI agents:

  1. Image Understanding — Qwen Vision analyses room type, lighting, furniture, and style cues
  2. Persona — generates a target buyer persona matched to the room
  3. Design — produces an interior design brief (style direction, colour palette, furniture list)
  4. Staging — edits the room photo via Wan2.7 image-to-image to realise the brief
  5. Story — writes a 3-beat character-driven narration script (no generic real-estate copy)
  6. TTS — synthesises the narration as a natural voiceover using Qwen TTS
  7. Video Gen — generates a 15-second 9:16 vertical reel from the staged image via HappyHorse
  8. Publisher — produces a social caption, hashtags, and CTA

All outputs — staged room image, voiceover WAV, vertical video, WebVTT subtitles, social post — are produced from a single API call. No camera, no editor, no copywriter.


How we built it

The backend is written in Rust using Tokio and Axum. Every agent is a typed async function that receives structured context from the previous stage and returns a typed Rust struct — not raw strings. This makes the pipeline testable, auditable, and easy to extend.

We use three distinct Qwen API surfaces:

  • OpenAI-compatible endpoint for all LLM agents (Persona, Design, Story, Publisher) via qwen3.7-max and qwen3.7-plus (vision)
  • DashScope native async polling API for image editing (Wan2.7), video generation (HappyHorse), and TTS (Qwen TTS Flash)
  • ffmpeg for merging video + voiceover + WebVTT subtitles into the final reel

The REST API exposes POST /api/run (multipart upload) and POST /api/run/url, with job polling via GET /api/jobs/:id. The frontend is React 18 + TypeScript + Vite with a dark premium UI — drag-and-drop upload, animated 9-step agent tracker, before/after room viewer, 9:16 phone-frame video player, and a full reasoning trail showing every agent's output.

Deployed as a Docker image (jfkongphop/roomreel-api) on Docker Hub, runnable on any container platform.


Challenges we ran into

DashScope async polling was the first real hurdle. Image generation, video generation, and TTS each use different request formats, different task ID paths, and different polling intervals. Building a reliable typed client for all three without a shared SDK required careful reading of the raw API docs and handling partial/failed task states gracefully.

Rust 2024 edition compatibility with the Docker build took iteration — rust:1.85 didn't support the edition, and ICU-related dependencies required upgrading to rust:1.86-slim.

Video + audio merge strategy required a two-path ffmpeg approach: Strategy A tries to blend background music (20%) with the voiceover (150% volume) using amix; Strategy B falls back to voice-only if the music track is unavailable or the merge fails.

The story agent prompt required significant tuning. Generic prompts produced exactly the generic copy we were trying to eliminate. The final prompt names a character, mandates sensory detail in every beat, requires an emotional arc, and explicitly bans a list of real-estate clichés.


Accomplishments that we're proud of

  • A fully typed Rust multi-agent pipeline where every stage's output is a concrete struct — not a string passed between prompt calls
  • The pipeline::run<F> function accepts a generic progress callback, meaning the exact same pipeline code drives the CLI, the REST API, and could drive WebSocket streaming without modification
  • The StoryAgent produces narration that reads like a short film, not a listing — measurably different from what a single-shot prompt produces
  • End-to-end: drop a JPEG, get a social-ready 9:16 reel with subtitles in one API call
  • A reasoning trail that surfaces every agent's full output in the frontend — the AI's decisions are transparent, not a black box

What we learned

  • Rust's type system is an excellent fit for multi-agent pipelines — if the agents compile, the data flow is correct
  • DashScope's image/video generation APIs require patience: polling intervals, task expiry, and output URL lifetimes all need to be handled explicitly
  • The quality of AI-generated copy is entirely determined by the constraints in the system prompt, not the model size — a well-constrained qwen3.7-max prompt outperforms a generic GPT-4 call for this domain
  • Separating the pipeline orchestrator from the REST server (via a typed callback) made the codebase significantly easier to test and extend

What's next for RoomReel

  • Multi-room batch processing — run the full pipeline across an entire property listing in parallel
  • Music bed generation — replace the static background music with a Qwen-generated ambient track matched to the room's mood
  • Agent memory — let the Persona and Story agents reference previous listings from the same agency to maintain brand voice consistency
  • Direct social publishing — OAuth integration to post the reel and caption directly to Instagram Reels and TikTok from the dashboard
  • Fine-tuned staging model — fine-tune Wan2.7 on luxury interior photography to improve staging quality for high-end listings

Built With

Share this project:

Updates