Live Streaming Reliability โ React Native + OvenMediaEngine
Rozpoฤet: $200.0
FIXED /
โญ 4.52 (57)
India
react-native, android, ios, phone, node.js
Preferred qualifications
- Experience: Expert
๐ญ. ๐๐ข๐ก๐ง๐๐ซ๐ง
We run a liveโstreaming platform. Streamers publish from a React Native mobile app; viewers also watch in a React Native mobile app, playing back through OvenMediaEngine (OME). Both ends are mobile apps โ there is no web client, so viewer playback is an inโapp LLHLS player, not a browser. We are hiring a freelancer to make the streamerโOMEโviewer path resilient to the realโworld failure modes of mobile streaming: backgrounding, network switches, OS interruptions, crashes, and disconnections.
๐ฆ๐ง๐๐๐ (๐๐๐ซ๐๐ โ ๐๐ข ๐ก๐ข๐ง ๐ฃ๐ฅ๐ข๐ฃ๐ข๐ฆ๐ ๐ฅ๐๐ฃ๐๐๐๐๐ก๐ ๐ง๐๐๐ฆ๐)
| Layer | Technology |
|------------------------|-------------------------------------------------|
| Streamer app | React Native (mobile) |
| Viewer app | React Native (mobile) โ inโapp LLHLS player (no web/browser client) |
| RTMP publishing module | @cbucket/react-native-livestream |
| Media server | OvenMediaEngine (OME) |
| Ingest protocol | RTMP |
| Viewer playback | LLHLS (LowโLatency HLS) |
| Backend | Stream state/control plane (Node or equivalent) |
๐ฎ. ๐ข๐ช๐ก๐๐ฅ๐ฆ๐๐๐ฃ ๐๐ก๐ ๐ฆ๐๐ข๐ฃ๐
This is a full endโtoโend engagement: streamer side โ backend โ viewer side. You take ownership of a working result, not of a single layer. Every requirement below may involve frontend and backend work.
- You may modify the contents of node_modules on the streamer side (specifically @cbucket/react-native-livestream) where required. Modifications must be documented and reproducible (patch file via patch-package or a maintained fork โ not an undocumented handโedit).
- You will write native code where a requirement cannot be met from JS. Several requirements below cannot be met from JS and explicitly require native work.
๐ฏ. ๐๐๐ฌ ๐๐๐ฆ๐๐๐ก ๐ฃ๐๐ฅ๐๐ ๐๐ง๐๐ฅ๐ฆ (๐๐๐ฅ๐๐๐๐ฌ ๐๐๐๐๐๐๐)
These are fixed inputs, not open questions:
- Reconnection grace window = 60 seconds. If a streamer's media stops (background, network drop, crash) and resumes within 60 s reโpublishing the same stream key, it is treated as the same logical broadcast and viewers resume seamlessly. After 60 s with no media, the broadcast is declared ENDED.
- Liveness is determined by actual media flow into OME, not by a client heartbeat. A client "I'm alive" ping is at most a secondary signal. The authoritative signal is whether OME is receiving RTMP bytes for the stream. (Reason: a backgrounded/suspended app cannot reliably send JS heartbeats, but the native media pipeline may still be streaming โ and a crashed app sends nothing regardless.)
- Viewer playback is LLHLS. On a clean end, the LLHLS playlist must be properly concluded (e.g. OME "Conclude HLS Live") so viewers receive a definitive ended state rather than indefinite loading.
๐ฐ. ๐๐ข๐ฅ๐ ๐ฅ๐๐ค๐จ๐๐ฅ๐๐ ๐๐ก๐ง๐ฆ
Each requirement is written with an acceptance test. "Done" means the acceptance test passes on the agreed device matrix โ not that it works in a quick demo. Vague terms like "seamless" and "graceful" are defined by their acceptance test, not by interpretation.
๐ฅ๐ญ โ ๐๐๐๐๐๐ฅ๐ข๐จ๐ก๐ / ๐๐ข๐ฅ๐๐๐ฅ๐ข๐จ๐ก๐ ๐ฆ๐ง๐ฅ๐๐๐ ๐๐ก๐
Required behavior: The app must keep the stream running while backgrounded and resume cleanly on return to foreground, holding the same broadcast across the transition (within the 60 s grace window).
Where the operating system prevents camera capture while the app is backgrounded, live video may pause โ in which case the viewer must see a black/placeholder frame with a loading indicator (this fallback is acceptable) โ and video must resume automatically when the app returns to the foreground. Audioโonly continuation in the background is also acceptable where supported. Use the platform's supported backgroundโexecution mechanism to keep the media pipeline and the connection to OME alive for as long as the OS permits.
๐๐ฐ๐ฐ๐ฒ๐ฝ๐๐ฎ๐ป๐ฐ๐ฒ ๐ง๐ฒ๐๐:
1. Start a stream. Background the app for up to 60 s, then foreground.
2. If background capture is supported: the viewer sees uninterrupted video (or a gap โค the agreed target) and the same session continues.
3. If background capture is not supported: the viewer sees audioโonly or a placeholder + loading indicator; on foreground, video resumes within the agreed gap as the same broadcast.
4. Background beyond 60 s โ the broadcast ends cleanly with no ghost stream; returning to foreground starts a new broadcast.
๐ฅ๐ฎ โ ๐ก๐๐ง๐ช๐ข๐ฅ๐ ๐ฆ๐ช๐๐ง๐๐๐๐ฆ (๐ช๐โ๐๐ โ ๐๐๐๐๐จ๐๐๐ฅ)
Switching networks midโstream must reconnect automatically and resume the same broadcast within the 60 s window.
- Define and meet a maximum media gap target on switch: ____ s (suggest โค 5 s).
- Viewer must show a reconnecting/loading state during the gap and recover automatically.
- On switch to cellular, handle the dataโcost dimension: agreed behavior is to warn the user / reduce bitrate / nothing (circle one).
๐๐ฐ๐ฐ๐ฒ๐ฝ๐๐ฎ๐ป๐ฐ๐ฒ ๐ง๐ฒ๐๐: While streaming on WiโFi, disable WiโFi (device falls back to cellular); reverse the test. Measure the media gap; confirm it meets target, the viewer recovers without manual action, and the backend keeps it as the same session (no new broadcast, no ghost).
๐ฅ๐ฏ โ ๐ ๐ข๐๐๐๐ ๐๐ก๐ง๐๐ฅ๐ฅ๐จ๐ฃ๐ง๐๐ข๐ก๐ฆ (๐ง๐๐ ๐ ๐ข๐ฆ๐ง ๐๐ข๐ ๐ ๐ข๐ก๐๐ฌ ๐๐ข๐ฅ๐๐ข๐ง๐ง๐๐ก ๐๐๐ง๐๐๐ข๐ฅ๐ฌ)
The stream must survive and recover from OSโlevel capture interruptions: incoming/outgoing phone calls, alarms, voice assistant, screen lock, system notifications, and another app taking the camera or microphone.
Hook into the OS capture/audioโsession interruption lifecycle: on interruption begin, pause the stream gracefully; on interruption end, autoโresume the same broadcast within the 60 s window. During any interruption the viewer must show the agreed paused/reconnecting state (consistent with R1) โ never a frozen UI or a false "live."
๐๐ฐ๐ฐ๐ฒ๐ฝ๐๐ฎ๐ป๐ฐ๐ฒ ๐ง๐ฒ๐๐: While streaming, place a real phone call to the device (and separately: trigger an alarm, lock the screen, open the native camera app). The stream pauses gracefully; after the interruption ends it autoโresumes as the same broadcast within the 60 s window; the viewer transitions cleanly through reconnecting โ live; no ghost stream is created.
๐ฅ๐ฐ โ ๐ฆ๐ง๐ฅ๐๐๐ โ๐ฆ๐๐๐ ๐๐ฅ๐๐ฆ๐ ๐๐๐ก๐๐๐๐ก๐ / ๐ก๐ข ๐๐๐ข๐ฆ๐ง ๐ฆ๐ง๐ฅ๐๐๐ ๐ฆ
If the streamer app crashes, is forceโquit, or loses connectivity, the platform must converge to the correct ENDED state and must never leave a "ghost" stream that viewers see as live.
This is primarily a backend requirement and cannot be satisfied frontendโonly. Required mechanism:
- The backend determines liveness from OME media flow โ poll OME's REST API per origin and use inboundโbyte deltas (not mere presence of the stream object, and not raw connection counters, which OME does not decrement reliably).
- A lease + 60 s grace window model: the stream's "live" lease is renewed by evidence of media flow; on expiry with no recovery, transition to ENDED.
- Session generation/epoch per publish session so a late or missing "close" event for an old session does not corrupt a newly reconnected session (see R5 for the RTMP race this addresses).
- On ENDED, force teardown via OME REST (Delete Stream) and Conclude the LLHLS output so viewers get a definitive ended state.
๐๐ฐ๐ฐ๐ฒ๐ฝ๐๐ฎ๐ป๐ฐ๐ฒ ๐ง๐ฒ๐๐: Forceโquit the app from the app switcher midโstream (and separately: enable airplane mode and leave it). The viewer shows reconnecting within ___ s, then ENDED within 60 s + margin; the backend stream state is ENDED; the stream no longer appears as active in OME; and crucially, no ghost stream remains after the grace window.
๐ฅ๐ฑ โ ๐ฅ๐๐๐ข๐ก๐ก๐๐๐ง๐๐ข๐ก (๐ฆ๐ง๐ฅ๐๐๐ ๐๐ฅ ๐๐ก๐ ๐ฉ๐๐๐ช๐๐ฅ)
Unified reconnection behavior covering all of the above causes (background, network switch, interruption, transient crash).
- Grace window = 60 s. Reโpublishing the same stream key within 60 s = resume same broadcast; after 60 s = new broadcast.
- Reconnection uses exponential backoff with a defined max attempt count / total duration (โค 60 s of streamerโside retry before giving up): ____.
- Generationโaware on the backend to handle the RTMP reconnect race: an RTMP reconnect is a new publish session at OME and the old session's close webhook may arrive late or never; the backend must not let a stale close event tear down the resumed session.
- Viewer side (LLHLS): the player must autoโrecover when segments resume, show a reconnecting state during the gap, and show a clean ended state when the playlist is concluded.
๐๐ฐ๐ฐ๐ฒ๐ฝ๐๐ฎ๐ป๐ฐ๐ฒ ๐ง๐ฒ๐๐:
(a) Drop the connection and restore it within 60 s โ same broadcast resumes for existing viewers.
(b) Restore after 60 s โ a new broadcast starts and the old one is ENDED.
(c) Rapid dropโandโreconnect โ verify exactly one active session (no duplicate/zombie session, no wrongful teardown of the live session).
๐ฑ. ๐๐๐๐๐ฉ๐๐ฅ๐๐๐๐๐ฆ
1. Streamerโside RN implementation (incl. native modules and any documented @cbucket/react-native-livestream patches/fork).
2. Backend streamโstate reconciler implementing the lease + 60 s grace + generation model (R4/R5), with OME REST/webhook integration.
3. Viewerโside LLHLS integration with full viewer state handling (loading, reconnecting, ended, error).
4. OME configuration changes required.
5. Documentation: architecture overview, the stream state machine, all tunable parameters, every node_modules modification, and run instructions for each acceptance test below.
6. Acceptance test toolkit (we will run these)
๐ฒ. ๐๐๐๐๐ฃ๐ง๐๐ก๐๐ ๐ง๐๐ฆ๐ง ๐ง๐ข๐ข๐๐๐๐ง
- Forceโquit: remove app from the app switcher midโstream.
- Network switch / loss: toggle WiโFi and airplane mode; use a network link conditioner / bandwidthโthrottling tool for degradedโnetwork and bitrateโadaptation tests.
- Interruptions: real inbound phone call, alarm, screen lock, launching the native camera app.
- Ghostโstream check: after each failure, query the backend state and OME's active streams โ both must read ENDED within the grace window.
Otvoriลฅ na Upwork
AI proposal draft
Generate a short cover letter for this job. Edit before sending.
Sign in to generate an AI proposal draft.
Prihlรกsiลฅ