Skip to content

BYOC: add streaming to BYOC#3841

Merged
ad-astra-video merged 23 commits intolivepeer:masterfrom
muxionlabs:master
Dec 22, 2025
Merged

BYOC: add streaming to BYOC#3841
ad-astra-video merged 23 commits intolivepeer:masterfrom
muxionlabs:master

Conversation

@ad-astra-video
Copy link
Copy Markdown
Collaborator

@ad-astra-video ad-astra-video commented Dec 18, 2025

What does this pull request do? Explain your changes. (required)

Final PR after splitting original PR #3727 into smaller PRs and refactoring BYOC into separate folder

Adds configurable streaming for BYOC entrypoint to go-livepeer. Uses trickle protocol to handle streaming for similar entrypoints and outputs from go-livepeer as live-video-to-video.

Streams can be any mix of the following:

  • video ingress via WHIP (with Gateway) or RTMP (with MediaMTX)
  • video egress via RTMP (with MediaMTX) or WHEP (with mediamtx)
  • SSE data output

Control and Events channels are created for every stream.

Streams are created with a POST request to /process/stream/start that will start the stream and reserve the capacity with an Orchestrator that is providing the BYOC capability. If video ingress is enabled, the client should then start a stream with WHIP or RTMP to the provided ingress URLs provided in the response. URLs for egress video, data, updates (control) and events are also included in the response as well as the stream_id. The stream_id is an integral part of the URLs provided to interact with the stream and is combined with a provided stream name in the /process/stream/start request.

Streams are stopped with a POST request to /process/stream/{stream_id}/stop. Orchestrators and Gateways track payment balance and the Gateway adjusts to the Orchestrators provided balance in new JobTokens provided at each payment interval every minute. Orchestrators will shutdown a stream when payment balance is zero.

Orchestrators use /ai/stream prefix for start/stop/update and payment. All outputs use trickle to send the outputs received from the workers to the Gateway.

Specific updates (required)

  • Add stream_gateway.go/stream_orchestrator.go to byoc folder
  • Copy code from server package as needed to allow the streaming endpoints to work
  • refactor job_rpc.go to job_gateway.go and job_orchestrator.go to reuse stream setup where made sense

How did you test each of these updates (required)

Does this pull request close any open issues?

No

Checklist:

@github-actions github-actions bot added the go Pull requests that update Go code label Dec 18, 2025
@codecov
Copy link
Copy Markdown

codecov bot commented Dec 18, 2025

Codecov Report

❌ Patch coverage is 36.21746% with 1666 lines in your changes missing coverage. Please review.
✅ Project coverage is 31.90751%. Comparing base (b45018a) to head (5f884fe).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
byoc/trickle.go 12.72727% 522 Missing and 6 partials ⚠️
byoc/stream_gateway.go 57.65379% 244 Missing and 52 partials ⚠️
byoc/stream_orchestrator.go 0.00000% 279 Missing ⚠️
byoc/job_orchestrator.go 33.88430% 226 Missing and 14 partials ⚠️
byoc/job_gateway.go 43.36570% 148 Missing and 27 partials ⚠️
byoc/utils.go 32.65306% 63 Missing and 3 partials ⚠️
byoc/job_auth.go 0.00000% 32 Missing ⚠️
byoc/payment.go 76.22951% 21 Missing and 8 partials ⚠️
byoc/byoc.go 79.59184% 18 Missing and 2 partials ⚠️
byoc/types.go 85.71429% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                 Coverage Diff                 @@
##              master       #3841         +/-   ##
===================================================
+ Coverage   31.55325%   31.90751%   +0.35426%     
===================================================
  Files            163         169          +6     
  Lines          39324       41216       +1892     
===================================================
+ Hits           12408       13151        +743     
- Misses         26022       27079       +1057     
- Partials         894         986         +92     
Files with missing lines Coverage Δ
byoc/types.go 46.15385% <85.71429%> (+46.15385%) ⬆️
byoc/byoc.go 77.51938% <79.59184%> (+77.51938%) ⬆️
byoc/payment.go 76.22951% <76.22951%> (ø)
byoc/job_auth.go 0.00000% <0.00000%> (ø)
byoc/utils.go 40.00000% <32.65306%> (-6.93878%) ⬇️
byoc/job_gateway.go 43.36570% <43.36570%> (ø)
byoc/job_orchestrator.go 33.88430% <33.88430%> (ø)
byoc/stream_orchestrator.go 0.00000% <0.00000%> (ø)
byoc/stream_gateway.go 57.65379% <57.65379%> (ø)
byoc/trickle.go 12.72727% <12.72727%> (ø)

... and 1 file with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b45018a...5f884fe. Read the comment docs.

Files with missing lines Coverage Δ
byoc/types.go 46.15385% <85.71429%> (+46.15385%) ⬆️
byoc/byoc.go 77.51938% <79.59184%> (+77.51938%) ⬆️
byoc/payment.go 76.22951% <76.22951%> (ø)
byoc/job_auth.go 0.00000% <0.00000%> (ø)
byoc/utils.go 40.00000% <32.65306%> (-6.93878%) ⬇️
byoc/job_gateway.go 43.36570% <43.36570%> (ø)
byoc/job_orchestrator.go 33.88430% <33.88430%> (ø)
byoc/stream_orchestrator.go 0.00000% <0.00000%> (ø)
byoc/stream_gateway.go 57.65379% <57.65379%> (ø)
byoc/trickle.go 12.72727% <12.72727%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Member

@rickstaa rickstaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ad-astra-video I’ve completed a full review of this pull request, and it’s very close to being ready to merge. Since much of the code was new to me, I had several questions and comments, some related to code outside the scope of this PR, which I captured in this document to avoid adding too much noise here. Let’s do a quick review together so I can leave more targeted feedback directly on the PR and we can move toward merging.

byoc/byoc.go Outdated

//ensure streamRequest is not nil or empty to avoid json unmarshal issues on Orchestrator failover
//sends the request bytes to next Orchestrator
if streamRequest == nil || len(streamRequest) == 0 {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nit but wouldn't this work given that len of nil byte gives true? Not to important but just something I noticed.

Suggested change
if streamRequest == nil || len(streamRequest) == 0 {
// Ensure a non-empty request body for failover
if len(streamRequest) == 0 {
streamRequest = []byte("{}")
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to ignore this one very minor. Just something I noticed.

Copy link
Copy Markdown
Member

@rickstaa rickstaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ad-astra-video general thing I found during my review outside of your changes.

It might still make sense to add a defer cancel() after creating the context. While it will eventually time out anyway, explicitly canceling ensures the cancellation happens immediately once the function returns and can help free resources sooner.

respCtx, cancel := context.WithTimeout(
    ctx,
    time.Duration(orchJob.Req.Timeout)*time.Second,
)
defer cancel()

Feel free to ignore as this is a nit.

if !exists {
req, err := http.NewRequestWithContext(ctx, "POST", orchJob.Req.CapabilityUrl+"/stream/stop", nil)
// set the headers
resp, err = sendReqWithTimeout(req, time.Duration(orchJob.Req.Timeout)*time.Second)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ad-astra-video does using resp and w in this function leads to race conditions as these are passed from the handler scope?

Copy link
Copy Markdown
Member

@rickstaa rickstaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ad-astra-video thanks for addressing my comments in the Notion doc. I’ve reviewed the latest changes and everything looks good for a merge.

As far as I can tell, this pull request should not introduce any side effects to the transcoding or live pipelines since it lives in its own namespace. While it does share some state, those components are intentionally shared across pipelines and are considered stable. The test you added should also flag any regressions caused by future changes in this area.

I did leave a few minor nits, but feel free to merge as-is.

Future improvements

For future reference, based on my discussion with Brad, these are areas he was considering exploring in follow-up pull requests, rather than firm commitments:

  • Was considering revisit creating a clearer separation between the legacy batch / batch-streaming pipelines and the newer byoc.live pipeline so it’s more obvious which components are shared across all pipelines.
  • Discussed potentially abstracting the orchestrator selection logic so it can be reused across these three byoc pipelines (see byoc/job_gateway.go#L67 and
    byoc/stream_gateway.go#L178)
  • Mentioned exploring whether batch-streaming can leverage the new byoc.live pipeline.
  • Considers looking into simplifying the logic at
    byoc/job_orchestrator.go#L222
    in job_orchestrator.go, which currently combines multiple responsibilities such as job proxying, periodic payment debits, and balance enforcement.
  • Discussed potentially separating payment logic in the orchestrator to simplify the code:
    byoc/stream_orchestrator.go#L181
  • Brad will add developer documentation describing the exact workings of BYOC and how it differs from Live.
  • Add WHEP support at a later stage.
  • May also revisit the weaker job/token credit verification logic (see verifyJobCreds and verifyTokenCreds ) and see if it can be reused to reduce divergence.

Further reduction of duplicate code

@j0sh, as discussed, @ad-astra-video duplicated some parts of the live pipeline to unblock onboarding additional demand partners and allow progress to continue independently.

We identified a few areas where INC could help reduce code duplication:

  • Would it make sense to make the methods in auth.go exportable so BYOC can reuse them and remove the BYOC-specific auth file?
  • Would it make sense to move the trickle logic in live_video_video.go into a shared trickle.go package? This would allow the community to benefit from INC’s work while reducing duplication.
  • BYOC also uses several methods in the byoc.utils file that are copied from the live pipeline. Are there any of these methods that make sense to move into a shared helper so they can be reused, given that they don’t change often?

Thanks for your consideration.

@ad-astra-video ad-astra-video merged commit 6b9a79c into livepeer:master Dec 22, 2025
20 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

go Pull requests that update Go code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants