Streaming to YouTube Live From an Android Phone With the Screen Off: The Whole Path, End to End — Updated July 2026

Short answer (updated July 2026): To stream your Android phone's camera to YouTube Live from anywhere with the screen off, you need an app that (1) creates a YouTube Live broadcast via the API, (2) pushes an H.264/AAC feed over RTMP to Google's ingest servers, and (3) runs inside a camera-typed foreground service so it survives the screen going dark. Background Camera RemoteStream does all three by default, keeps recording locally the whole time, and defaults broadcasts to unlisted. General-purp
Short answer (updated July 2026): To stream your Android phone's camera to YouTube Live from anywhere with the screen off, you need an app that (1) creates a YouTube Live broadcast via the API, (2) pushes an H.264/AAC feed over RTMP to Google's ingest servers, and (3) runs inside a
camera-typed foreground service so it survives the screen going dark. Background Camera RemoteStream does all three by default, keeps recording locally the whole time, and defaults broadcasts to unlisted. General-purpose mobile streamers (CamON Live Streaming, CameraFi Live, Streamlabs) can also push to YouTube Live, but they're built around a screen-on, foreground streaming session — screen-off, local-first recording that keeps running is the specific thing this pipeline is designed for.
Why this path is harder than it looks
"Stream my phone's camera to YouTube Live" sounds like a single feature. Under the hood it's four separate systems that have to cooperate: an OAuth-authorized call into the YouTube Live API to create a broadcast, an RTMP client that opens a raw socket to Google's ingest servers, a hardware encoder turning camera frames into an H.264/AAC bitstream, and an Android foreground service keeping the whole thing alive after the screen goes dark. Any one of them failing quietly takes the stream down.
I build Background Camera RemoteStream, a privacy-first Android camera app whose whole point is that it keeps recording and streaming with the screen off and stores everything locally by default. The YouTube Live path is the one place where footage deliberately leaves the device, so it's worth being precise about exactly how it works. This is a walkthrough of the full pipeline — the API dance, the RTMP handshake, the encode loop, and the screen-off plumbing — written for anyone who wants to build the same thing or just understand what their phone is actually doing when it says "you're live."
Stage 1: Getting a place to push pixels (the YouTube Live API)
You can't just open a socket to YouTube and start shoving video. YouTube's ingest endpoint won't accept a stream it doesn't already know about. So the first stage is entirely HTTP, and it produces exactly two things you need for later: an ingestion URL and a stream key.
The YouTube Live Streaming API models a live event as two linked resources. A liveBroadcast is the public-facing thing — the watch page, the title, the privacy setting, the scheduled start time. A liveStream is the plumbing — the actual audio/video pipe that carries bytes. They start life independent and you glue them together.
The sequence, after an OAuth 2.0 flow that gets you a token scoped to the user's YouTube channel:
-
liveBroadcasts.insert— create the broadcast. This is where privacy lives. Settingstatus.privacyStatustounlistedmeans the stream exists at a real URL but never appears in search, on the channel page, or in recommendations. That's the default the app uses: you get a link you can hand to exactly the people who should see the room, and no one else stumbles onto it. -
liveStreams.insert— create the stream and, critically, setcdn.ingestionTypetortmp. The response comes back with acdn.ingestionInfoobject, and that is the payload the rest of the pipeline is built around:ingestionAddress(the RTMP URL, typicallyrtmp://a.rtmp.youtube.com/live2) andstreamName(the stream key — the secret that authorizes your push). -
liveBroadcasts.bind— attach the broadcast to the stream by ID. A broadcast can be bound to only one stream at a time, though a single stream can back multiple broadcasts. Skip this and you have two orphaned resources and no live event. -
liveBroadcasts.transition— once bytes are actually arriving at the ingest endpoint and YouTube reports the stream health as good, you move the broadcasttesting→live. Transition too early, before data is flowing, and the API rejects it.
Two things matter here for a privacy-first app. The stream key is a bearer secret — anyone holding it can broadcast to that channel — so it never gets logged, never gets written to shared storage, and lives only as long as the session. And because the broadcast is created unlisted by default, the visibility decision is made explicitly by the user at creation time, not left to a permissive default.
Stage 2: The RTMP handshake
Now you have rtmp://a.rtmp.youtube.com/live2 and a stream key. RTMP (Real-Time Messaging Protocol) runs over a plain TCP connection, and before a single frame of video moves, both ends perform a fixed three-packet handshake. It's one of those protocol details that's invisible when it works and completely opaque when it doesn't, so it's worth knowing.
After the TCP connection is up, the exchange is symmetric — the client sends C0, C1, C2 and the server answers with S0, S1, S2:
-
C0 is a single byte: the protocol version,
0x03. - C1 is 1536 bytes — the first 4 are an epoch timestamp, the next 4 are zero, and the remaining 1528 are random. The client fires it off without waiting for the server to acknowledge C0.
- C2 is another 1536-byte packet that's essentially an echo of the server's S1, with the second 4-byte field replaced by the time S1 was read.
When C2 and S2 have been exchanged, the handshake is complete and the connection is established. Details per the Adobe RTMP specification. Only then do the AMF command messages flow — connect (naming the live2 application), createStream, and publish (where the stream key finally gets sent). Get the handshake byte layout wrong and the socket just dies with no useful error, which is why using a battle-tested RTMP layer beats hand-rolling one.
Stage 3: Turning camera frames into a bitstream
RTMP moves bytes; it doesn't make them. Between the camera sensor and the socket sits the encoder, and on Android that means MediaCodec backed by the device's hardware H.264 encoder — because software-encoding 1080p in real time would cook the battery and the SoC in minutes.
The elegant part of the Android stack is that you never have to copy raw pixels around in your own code. MediaCodec can hand you an input Surface, and Camera2's CameraCaptureSession can be told to render straight into that Surface as one of its capture targets. Frames flow sensor → encoder without a round-trip through application memory. The encoder emits H.264 NAL units; audio from AudioRecord goes through a parallel AAC MediaCodec. Both elementary streams then get packetized into FLV tags (RTMP's native container) with correct timestamps so audio and video stay in sync, and pushed over the socket from stage 2.
A few things this app cares about at this layer:
- Bitrate discipline. A phone on Wi-Fi or LTE has a variable uplink. The encoder target bitrate has to be conservative enough that the RTMP send buffer doesn't back up; when it backs up, latency climbs and YouTube's health indicator goes yellow, then red. Watching the send-queue depth and easing the bitrate is what keeps a stream stable over a long session.
-
Keyframe interval. YouTube wants a keyframe (IDR) every couple of seconds. Too sparse and viewers who join mid-stream stare at a gray box; the encoder's
I-frame intervalis set accordingly. - The camera keeps its own recording. Streaming is an additional consumer of the frames, not a replacement. The local, on-device recording — the privacy-first default — keeps running regardless of whether the network stutters. The bytes going to YouTube are a copy; the originals never leave the phone unless you send them.
For the mechanics of driving Camera2 correctly while all this happens in the background — orientation, focus, and exposure without an interactive preview — I wrote that up separately in Camera2 API: handling orientation, focus, and exposure in the background.
Stage 4: Keeping it alive with the screen off
Here's where most "just stream the camera" tutorials fall apart, because they assume the app is in the foreground with the screen on. The entire value of this app is that it isn't. You lock the phone, drop it in a corner pointed at the room, and it keeps streaming. Android does not want to let you do that, and for good reasons — a backgrounded app holding the camera open is exactly the shape of spyware.
The mechanism that makes it legitimate is a foreground service typed camera. Since Android 14, a service that uses the camera while the app isn't visible must declare foregroundServiceType="camera" in the manifest, hold the matching FOREGROUND_SERVICE_CAMERA permission, and post an ongoing, non-dismissable notification. That notification is not a formality — it's the OS-enforced honesty tax. The user always sees that the camera is active, even with the screen off, because Android won't let the service run silently. A privacy-first app should want that constraint, not fight it.
The service owns the long-lived work: the Camera2 session, the two MediaCodec instances, and the RTMP socket all live inside it, not in an Activity that gets destroyed the moment the screen turns off. It also has to hold a partial wake lock so the CPU keeps encoding while the display sleeps, and it has to handle the reality that the OS can still tear things down under memory pressure — so reconnection logic and clean session teardown aren't optional. I went deeper on this specific piece in foregroundServiceType="camera": keeping a camera alive with the screen off on Android 14.
The two ways to watch, and why both exist
Worth being explicit about the two very different remote-viewing paths this app supports, because they make opposite trade-offs:
- Unlisted YouTube Live is the from-anywhere path. It rides Google's global CDN, so you can watch from a different network, a different country, on any device with a browser. The cost is that the frames pass through Google's infrastructure to get there — which is why it's opt-in, per-session, and unlisted by default.
- The built-in LAN web server is the stays-home path. The app embeds a small Ktor HTTP server, so any browser on the same Wi-Fi can pull the live view with nothing leaving the local network — no account, no cloud, no third party. That's the privacy-maximal option, bounded to same-network viewing. I wrote about that design in embedding a Ktor web server inside an Android app.
Same camera, same screen-off foreground service, two egress paths with honestly different privacy profiles. You pick per session.
Putting it together
End to end, one live session looks like this: OAuth token → liveBroadcasts.insert (unlisted) → liveStreams.insert (rtmp) → read ingestionAddress + streamName → liveBroadcasts.bind → open TCP → RTMP C0/C1/C2 handshake → connect/createStream/publish with the stream key → Camera2 renders into a MediaCodec input Surface → H.264 + AAC muxed to FLV over RTMP → once bytes arrive, transition to live → and all of it hosted inside a camera-typed foreground service so it survives the screen turning off. Meanwhile the local recording keeps writing to device storage, untouched.
None of these stages is exotic on its own. The engineering is in making them cooperate reliably on a battery-powered device with a flaky uplink and an operating system that's actively suspicious of background camera use — and in making the privacy defaults (unlisted broadcasts, local-first storage, a mandatory visible notification) the path of least resistance rather than a setting you have to hunt for.
If you want to see it running rather than read about it, the app is on Google Play, and there's more on the project at superfunicular.com. It was built over 75+ AI-assisted development sessions, and the YouTube Live path was one of the more satisfying things to get stable — four systems that each want to fail independently, all finally agreeing to stay up with the screen off.
Want the non-developer version — just picking a free app to watch your house or pet? See Best Free, No-Subscription Apps to Turn an Old Android Phone Into a Local-Only Security Camera and Can I Replace My Nest, SimpliSafe, or Kasa Cloud Cam With an Old Android Phone?.
Building the same thing? The two hardest bugs, in my experience, are the RTMP handshake byte layout (silent socket death) and the Android 14 foreground-service-type declaration (the service just won't start without it). Get those two right and the rest is tuning.
