Skip to content

fix(producer): attach src URL to ffprobe failures for compile-phase attribution (STUDIO-5433) - #3033

Open
vanceingalls wants to merge 1 commit into
mainfrom
via/studio-5433-ffprobe-src-url
Open

fix(producer): attach src URL to ffprobe failures for compile-phase attribution (STUDIO-5433)#3033
vanceingalls wants to merge 1 commit into
mainfrom
via/studio-5433-ffprobe-src-url

Conversation

@vanceingalls

Copy link
Copy Markdown
Collaborator

What

Wrap the video-branch extractMediaMetadata and probeMediaProfile calls in resolveMediaDuration (packages/producer/src/services/htmlCompiler.ts) with a withSrcContext helper that re-throws with the remote src appended as [src=<url>]. The URL is passed through redactTelemetryString first so pre-signed URL signatures never reach telemetry.

Why

STUDIO-5433 — enterprise customer mdave@manh.com was blocked from generating AI Studio videos, surfacing in Datadog as [FFmpeg] ffprobe exit with code 1: [mov,mp4,m4a,3gp,3g2,mj2 @ 0x...] moov atom not found\n[input]: Invalid data found when processing input. runFfprobe at engine/utils/ffprobe.ts:74-79 intentionally redacts the local filePath from the error (see redactFfprobeInput — same file, lines 13-35), so the failure carries no attribution and identifying the offending source requires dumping the Temporal activity history for the workflow.

Root-cause investigation confirms the failing file is MOV/MP4-family (per the demuxer signature) and comes from astral-agent's composition-HTML preview pipeline (path prefix astral-agent/output/hf-preview-*), but the specific <video src> URL wasn't recoverable from indexed Datadog logs — the signed URL had expired 3h before investigation, and neither the producer worker nor the streaming activity logs any per-src URL context around the probe call.

This change surfaces the URL so the next occurrence is diagnosable directly from the render error in Datadog, without a Temporal history dump. That unblocks writer-side hardening as a follow-up.

Preserves fail-fast semantics: the video branch still throws (aborts the compile), unlike the audio branch's deliberate graceful-degrade to duration=0. Only the error message is enriched; the control flow is unchanged.

How

  1. packages/producer/src/services/htmlCompiler.ts

    • New withSrcContext(error) helper inside resolveMediaDuration that wraps error.message with [src=<redactTelemetryString(src)>] and preserves the original stack.
    • Video-branch probeMediaProfile catch re-throws via withSrcContext (was: bare throw error).
    • Video-branch extractMediaMetadata newly wrapped in try/catch that re-throws via withSrcContext (was: uncaught, so the caller saw the bare [input]-redacted ffprobe message).
    • Adds redactTelemetryString import from @hyperframes/core (already exported at packages/core/src/index.ts:255).
  2. packages/producer/src/services/htmlCompiler.test.ts

    • New describe("STUDIO-5433 — ffprobe failure includes src URL for attribution") block with a compileForRender integration test: writes a 0-byte assets/clip.mp4, references it from a <video src> tag, asserts the thrown error message contains [src=assets/clip.mp4] AND still carries the original ffprobe diagnostic so downstream failure classifiers continue to match.

Test plan

  • Local repro: 0-byte mp4 → compileForRender → error message contains [src=assets/clip.mp4] (integration test above).
  • Preserves fail-fast semantics — video branch still throws (assertion on thrown error type + message content).
  • Query-string signatures are stripped via the existing redactTelemetryString (packages/core/src/telemetryRedaction.ts:8redactUrlQueryStrings) — no pre-signed URL secrets leak into Datadog.
  • Focused CI must pass; hosted CI to follow.
  • Follow-up (separate PR pending URL recovery): identify the astral-agent writer that produces the actual failing derivative and add _probe_section_integrity fail-closed at the write site (the durable fix — this PR is diagnosability defense-in-depth).

Enterprise release / feature flag holdout

  • This change is not behind a feature flag (small diagnostic improvement on an existing error path; preserves failure semantics unchanged).
  • This change is behind a feature flag

UX/Screenshot recording

  • No UI impact — enriches a producer-worker error message read only in Datadog.

— Via

…ttribution (STUDIO-5433)

## What

Wrap the video-branch `extractMediaMetadata` and `probeMediaProfile` calls in
`resolveMediaDuration` (`packages/producer/src/services/htmlCompiler.ts`) with a
`withSrcContext` helper that re-throws with the remote `src` appended as
`[src=<url>]`. The URL is passed through `redactTelemetryString` first so
pre-signed URL signatures never reach telemetry.

## Why

STUDIO-5433 — enterprise customer `mdave@manh.com` was blocked from generating
AI Studio videos, surfacing in Datadog as `[FFmpeg] ffprobe exit with code 1:
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x...] moov atom not found\n[input]: Invalid data
found when processing input`. `runFfprobe` at `engine/utils/ffprobe.ts:74-79`
intentionally redacts the local `filePath` from the error (see
`redactFfprobeInput` — same file, lines 13-35), so the failure carries no
attribution and identifying the offending source requires dumping the Temporal
activity history for the workflow.

That dump is expensive-per-occurrence and blocks debugging on operator
availability. The demuxer signature (`mov,mp4,m4a,3gp,3g2,mj2`) tells us the
file is MOV/MP4-family, and the workflow_id tells us which HyperFrames
composition element failed — but the *actual URL* that ffprobe was handed is
lost. This change surfaces the URL so the next occurrence is diagnosable
directly from the render error in Datadog, without a Temporal history dump.

Preserves fail-fast semantics: the video branch still throws (aborts the
compile), unlike the audio branch's deliberate graceful-degrade to
`duration=0`. Only the error *message* is enriched; the control flow is
unchanged.

## How

1. `packages/producer/src/services/htmlCompiler.ts`
   - New `withSrcContext(error)` helper inside `resolveMediaDuration` that
     wraps `error.message` with `[src=<redactTelemetryString(src)>]` and
     preserves the original stack.
   - Video-branch `probeMediaProfile` catch re-throws via `withSrcContext`
     (was: bare `throw error`).
   - Video-branch `extractMediaMetadata` newly wrapped in try/catch that
     re-throws via `withSrcContext` (was: uncaught, so the caller saw the
     bare `[input]`-redacted ffprobe message).
   - Adds `redactTelemetryString` import from `@hyperframes/core` (already
     re-exported at `packages/core/src/index.ts:255`).
2. `packages/producer/src/services/htmlCompiler.test.ts`
   - New `describe("STUDIO-5433 — ffprobe failure includes src URL for
     attribution")` block with a `compileForRender` integration test:
     writes a 0-byte `assets/clip.mp4`, references it from an `<video src>`
     tag, asserts the thrown error message contains `[src=assets/clip.mp4]`
     AND still carries the original ffprobe diagnostic so downstream
     failure classifiers continue to match.

## Test plan

- [x] Repro locally: 0-byte mp4 → `compileForRender` → error message contains
      `[src=assets/clip.mp4]` (test above).
- [x] Preserves fail-fast semantics — video branch still throws (assertion on
      thrown error).
- [ ] Focused CI must pass; hosted CI to follow.
- [ ] Follow-up (separate PR pending URL recovery): identify the writer that
      produces the actual failing derivative and add `_probe_section_integrity`
      fail-closed at the write site (the durable fix — this PR is
      diagnosability defense-in-depth).

## Enterprise release / feature flag holdout

<!-- pr-check:enterprise-ff:start -->
- [x] This change is not behind a feature flag (small diagnostic improvement
      on an existing error path; preserves failure semantics unchanged).
- [ ] This change is behind a feature flag
<!-- pr-check:enterprise-ff:end -->

## UX/Screenshot recording

<!-- pr-check:ui-impact -->
- [x] <!-- pr-opt:no-ui-impact --> No UI impact — enriches a producer-worker
      error message read only in Datadog.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant