Serve a rendered ad into a streaming break - #302
Merged
Merged
Conversation
Adds the endpoint a player calls when it wants something to play in an ad break, and the lookup that turns a chosen creative into a file to fetch. Selection, the auction and the impression are not redone. They are serveAd's, exactly as they are for a banner, because a second selection path would be a second set of numbers and the one not wired to billing is the one that quietly gives inventory away. This only answers the question serveAd cannot: given the creative it picked, which file should this player load? Audio by default. The properties most likely to call this are music and radio players — nixamp already fetches an endpoint of this shape from its ad break handler — and handing a video URL to something with nowhere to show a picture is worse than handing it audio it can certainly play. A video request gets the 720p rendition rather than the 1080p master: the master is the download an advertiser keeps, and making a phone fetch it to watch five seconds spends their data on pixels the screen cannot show. Only published_revision is servable, and there is no fallback to another revision or another profile. A revision becomes published when the worker has validated it; serving the newest instead would put media on air that was never approved, and a silent fallback would do it without saying so. An unfilled break returns 200 with a null url rather than an error. A break nobody can fill simply does not happen and the listener keeps their content, which is the only safe default when the alternative is dead air. The one case that is logged is a creative that won the auction and has no media: that is a campaign winning inventory it cannot fill, which is worth knowing about. Nothing is wired to a property yet. nixamp's client calls /api/ads/next and no route implements it; that bridge is the next piece. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ThreatCrush Security Scan48 finding(s) HIGH/CRITICAL: 2 | MEDIUM: 31 | LOW: 15
Snippets are redacted; ThreatCrush never prints matched credential material. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The first piece of actually serving these ads to listeners. Adds
GET /api/ads/stream— what a player calls when it wants something to play in a break — and the lookup that turns a chosen creative into a file to fetch.Selection is not reinvented
The auction and the impression are serveAd's, exactly as they are for a banner. A second selection path would be a second set of numbers, and the one not wired to billing is the one that quietly gives inventory away. This route only answers the question serveAd cannot: given the creative it picked, which file should this player load?
Audio by default
nixamp — which is where this is headed — is a music player that already fetches an endpoint of this shape from its ad-break handler, and it has nowhere to put a picture. Handing it a
<video>URL would be worse than handing it audio it can certainly play.A video request gets 720p, not the 1080p master: the master is the download an advertiser keeps, and making a phone fetch it to watch five seconds spends their data on pixels the screen cannot show.
Only what was approved
Only
published_revisionis servable, with no fallback to another revision or another profile. A revision becomes published when the worker has validated it; serving the newest instead would put media on air that was never approved, and a silent fallback would do it without saying so.An unfilled break is not an error
It returns
200with a null url. A break nobody can fill simply does not happen and the listener keeps their content — the only safe default when the alternative is dead air. Every failure path, including exceptions, returns that.The one case that is logged: a creative that won the auction and has no media. That's a campaign winning inventory it cannot fill, which is worth knowing about.
Not yet wired to anything
nixamp's client calls
/api/ads/nextand no route implements it — so today its breaks fetch, 404, and silently play nothing. That bridge is the next piece, along with a slot for the property.Verification
6 tests covering the two real risks: never serving an unpublished revision, and giving each player the right profile. 2596 passed / 1 failed repo-wide — the pre-existing
tracker-geofailure. Typechecks clean.