Skip to content

mostlyright.weather.earnings.capture.q4

Q4 browser-webcast capture adapter (Phase 27, 27-03; RESEARCH §2).

Q4 (events.q4inc.com / *.q4cdn.com) is the widest large-cap coverage provider (~50% of the S&P 500). Its browser-webcast template exposes a STATIC progressive MP4 at https://static.events.q4inc.com/edited-recordings/{eventId}/{uuid}.mp4 that answers a plain ranged GET with no cookies, any/no referer → 206 — the guest form gates the PAGE, not the asset (RESEARCH §2 “Fetch that worked”).

Capture path (public, no circumvention — D-27.9): : 1. cold ranged-GET the static static.events.q4inc.com/.../*.mp4 directly with a UA only — NO cookie / token / Authorization header. For the 27-03 VOD/replay path NO guest-page navigation is required: the static replay MP4 is cold-fetchable directly because the guest form gates the PAGE, not the asset (RESEARCH §2 “Fetch that worked”). A guest-form navigation seam is kept for later GATED providers (Notified MX-gate, etc.), but the 27-03 static asset does not need it. 2. extract audio to a TRANSIENT temp file and return an AudioArtifact whose cleanup() deletes it (never persisted).

The analyst template (Q4 dial-in) is a telephone bridge with zero HTTP media — CaptureNotAvailable is raised so the caller routes to dial-in / skip (RESEARCH §2 CHWY), never silently producing empty audio.

NOTE: this is the VOD/replay path — the static MP4 exists only AFTER the call. The live-during-call Q4 edge (Amazon IVS playback.live-video.net) is the live() seam added in 27-09.

Q4CaptureAdapter()Q4 browser-webcast VOD capture over the public guest path (RESEARCH §2).

class mostlyright.weather.earnings.capture.q4.Q4CaptureAdapter

Section titled “class mostlyright.weather.earnings.capture.q4.Q4CaptureAdapter”

Bases: CaptureAdapter

Q4 browser-webcast VOD capture over the public guest path (RESEARCH §2).

capture(event, , client=None, transport=None, tmp_dir=None, **_)

Section titled “capture(event, , client=None, transport=None, tmp_dir=None, **_)”

Cold-fetch the Q4 static MP4 and extract transient audio.

event carries ticker / call_id / media_url (the sniffed static.events.q4inc.com/.../*.mp4 currentSrc). When media_url is absent the event is the analyst dial-in template (no HTTP media) — CaptureNotAvailable is raised.

client may be an injected httpx.Client (a guest-flow session for later gated providers). transport is the explicit transport the cold MEDIA fetch rides on — tests pass an httpx.MockTransport directly. The cold MEDIA fetch is ALWAYS issued through a FRESH UA-only client built here (from transport when given) — it deliberately does NOT inherit the injected client’s cookies or default headers, so no cookie / token / Authorization can ever leak onto the asset GET (the guest form gates the page, not the asset — RESEARCH §2). When only client is given (no explicit transport) the media fetch reuses that client’s transport via its public httpx.Client._transport seam so the mock host still serves the request, but starts from a clean header set and empty cookie jar.

media_url is validated (https + Q4 media host) BEFORE any fetch — an unvalidated cold GET would be an SSRF sink (D-27.9). The media fetch rides a GENEROUS timeout (not httpx’s flat 5s default, which would abort a full MP4 stream at the read deadline). A BORROWED transport (from an injected client or the explicit transport param) is NEVER closed here — only a transport this method created itself is; closing a borrowed shared transport would break the caller’s injected client.

A 2xx/206 that carries a ZERO-byte body (an expired / edited replay that answers the range but serves no media) raises CaptureNotAvailable instead of writing an empty MP4 and flowing to STT — the byte count is tracked during the stream loop and an empty result fails loud.

The fetch is also bounded on SIZE and TOTAL TIME (D-27.9 resource-safety): media_url is external event data and the SSRF allow-list bounds only the host, not the object size, so an over-_MAX_MEDIA_BYTES asset is rejected up front from its declared Content-Range/Content-Length and, as a backstop, aborted mid-stream once the written bytes exceed the cap; a slow-drip source that never trips the per-op read timeout is aborted at the _MEDIA_TOTAL_TIMEOUT wall-clock deadline. All abort paths unlink the partial MP4 via the outer finally — an oversized/slow asset can never fill the ingest host’s temp disk or flow to STT.

Return True when url is a Q4 webcast/asset host.

  • Return type: bool
  • Parameters: url (str)