Skip to main content
WMA connects your application to a fal runner through WebRTC. A session can exchange control messages, audio, and video. Use fal.wma.App to manage the session and fal.wma.AiortcPeer to connect a Python media pipeline.
WMA is experimental, including when it ships in a stable fal package. Pin your SDK versions because the WMA API can change. The Python examples require fal 1.81.4 or later and Pydantic 2. The browser walkthrough uses a separately versioned JavaScript prerelease.

Deploy your first app

Start with the generated-video example. It runs on a CPU and requires no camera, model weights, or GPU. You can change its colors and speed while the video streams.

1. Install and authenticate

Use Python 3.12 for this walkthrough. Create a virtual environment, then install the SDK:
On Windows PowerShell, activate the environment with .venv\Scripts\Activate.ps1. If your package index cannot find 1.81.4, wait for the PyPI publishing workflow to finish. A GitHub release can exist before its package is available on PyPI. The wma extra installs local WebRTC dependencies. WMA apps also receive aiortc in their runner requirements. Your account needs deployment access and WMA bridge access. Installing the package does not grant either permission.

2. Download and deploy the video example

Download the example from the matching SDK release:
Keep the application ID from the deployment output. You will use this ID in the playground and browser client. The example uses an XS CPU runner, permits two simultaneous sessions per runner, and limits each session to two minutes. Runner compute can incur charges. Disconnect when you finish testing.

3. Connect in the playground

  1. Open your deployed app in the fal dashboard.
  2. Select its /start-session playground.
  3. Select Connect and wait for the video.
  4. Select Fast sunset, then select Send message.
  5. Confirm that the colors and speed change.
  6. Select Disconnect to end the session.
The playground displays an AsyncAPI link and controls for the declared messages. If you see an SDP text field instead, check the realtime contract.

Choose an example

Each example includes a realtime contract and deployment requirements. Download the file, then deploy the named class with --auth private. The camera examples need browser camera permission. Motion measurements use pixel differences, not an object detector. For your own frontend, follow Connect a browser to WMA.

Build your own app

Subclass fal.wma.App and implement create_backend(session). Return an AiortcPeer, or implement PeerBackend for your own transport. The following complete app echoes typed control messages. Save it as wma_echo.py.
Deploy it with:
The echo handler sends back the received message. Contract schemas describe your API but do not validate incoming messages automatically. For application commands, validate the payload inside your handler with your Pydantic model before you use it. The callback passed to AiortcPeer receives the peer connection. Attach outgoing tracks with pc.addTrack(track). Register a pc.on("track") handler to process incoming media. The video and camera examples demonstrate both patterns.

Describe your app for the playground

Declare realtime_contract on every app that needs the WMA playground. The SDK generates AsyncAPI and links it from the /start-session OpenAPI operation through x-fal-realtime. This metadata enables Connect/Disconnect controls, message forms, examples, and media previews. Use Pydantic models for client_messages and server_messages. Add MessageExample entries for commands that customers can try. Use MediaContract to describe the actual media tracks. Track directions are always from the client’s perspective: For example, a camera-to-video app declares:
Redeploy after changing the contract, then refresh the playground. Transport can work without a contract, but the SDK cannot infer your messages or tracks. Core sessions support Pydantic 1. Typed contracts and schema rendering require Pydantic 2.

Session lifecycle and cleanup

The client sends its offer through the WMA bridge. The bridge forwards it to your app’s POST /start-session endpoint. The response streams the answer and keeps the HTTP connection open for the session’s lifetime. Media and control messages travel through WebRTC, either directly or through TURN. Closing the session closes its backend and finalizes deferred usage. Do not add application heartbeat or close routes for this lifecycle. Keep mutable state inside create_backend so different sessions do not share controls accidentally. Use session.create_task() for background work that must stop with the session. Bind resources with session.bind_backend(backend) before setup work that can fail. AiortcPeer stops its attached outgoing tracks during cleanup. Use a separate relay subscription when sessions share a media source. It limits the initial connection wait to 35 seconds. Set disconnected_grace_seconds if you want a bounded wait after a transient disconnect. session.send(message) returns False when the channel cannot accept a message or its buffer is full. Drop stale updates or retry later. A worker thread’s True result confirms queue acceptance, not delivery to the client.

ICE, billing, and deployment

Use RunnerIceConfig.from_bridge() with the forwarded offer, as shown above. It validates the supplied ICE servers before use. TURN permits connections on networks where a direct path fails. A successful local connection does not prove that TURN works. For metered application usage, call session.add_billable_units(n) for delivered work. Use session.cap_billable_units(n) before finalization if cleanup identifies undelivered work. Deferred usage is zero on setup failures by default. Runner compute can still incur charges. Billing report failures require operational follow-up. The base app includes the FAL_KEY secret for its billing reporter. Preserve it if your subclass overrides secrets. Configure the required runner secrets and endpoint pricing before using deferred billing. Your browser application’s API key belongs on its server, never in browser code. Before customer handoff, verify these behaviors against the deployed app:
  • Connect with the intended client and network.
  • Exchange the declared controls and media.
  • Test TURN on a network that requires relay connectivity.
  • Disconnect and reconnect with a new session.
  • Confirm that cleanup stops background work and releases resources.
  • Confirm the settled billing amount for delivered work.

Troubleshooting

See the SDK guide for module details and custom backend responsibilities.