Skip to content

Instantly share code, notes, and snippets.

@object
Created September 22, 2026 19:36
Show Gist options
  • Select an option

  • Save object/2f81b0ce7c94147e94813b964507ca21 to your computer and use it in GitHub Desktop.

Select an option

Save object/2f81b0ce7c94147e94813b964507ca21 to your computer and use it in GitHub Desktop.
AV1 overlapping bitrate session transcript

Session transcript — AV1 overlapping bitrate bug

Date: 2026-09-22 Working directory: C:\Projects\NRK\distribution-oddjob Branch: bugfix/overlap-av1-bitrate @ df5879cd2 Model: Claude Opus 5 (1M context), via Claude Code

Reconstructed from the session context. User and assistant messages are verbatim. Tool calls are listed in order with their outputs abridged where long — elisions are marked […]. Long file reads are summarised as the range read rather than reproduced.


Turn 1 — user

I am struggling to find a business logic error in my code. I wrote test that reproduces it, it's in the project IsolatedTests and it is called "When a program gets retranscoding with disabled codec and overlapping bitrate, s3 contains files and smil includes latest fileset". I need to find the error so this test will pass.

Turn 2 — assistant

I'll start by finding the test and understanding what it's checking.

Tools (parallel):

  1. Grep pattern retranscoding with disabled codec and overlapping bitratetests\IsolatedTests\PsTests.fs (1 file)
  2. Bashgit log --oneline -3 && git show --stat HEAD && git show --stat HEAD~1 → ``` df5879cd2 fix error in test, correct smil content 83e9ba20d create failing test for AV1 overlapping bitrate bug cea08a07f update isolated test urls to not use localhost (#4136)
    `df5879cd2`: `tests/IsolatedTests/PsTests.fs | 29 +++++-----`
    `83e9ba20d`: `src/Core/Config.fs | 2 +-`, `tests/IsolatedTests/PsTests.fs | 101 +++++++--`
    
    

Next tool: Bash — full git show HEAD~1 and git show HEAD.

Key content of 83e9ba20d: adds generatePsFileNames, changes assignVideoFiles to take (string * string) list (filename, codec) pairs, adds assign264VideoFiles / assignVideoFilesWithCodec wrappers, adds the new theory test. Also changes Config.fs:

-                Unchecked.defaultof<'a>
+                Unchecked.defaultof<'a> //TODO: should we use defaultValue here?

df5879cd2 reformats and corrects the final smil assertion to filter out the AV1 file:

-            awaitS3Smil MediaType.Video folderPath newFileNames List.Empty List.Empty SmilVersion.Latest
+            awaitS3Smil MediaType.Video folderPath (newFiles |> List.filter (snd >> ((<>) "av1")) |> List.map fst) List.Empty List.Empty SmilVersion.Latest

Turn 3 — assistant (investigation continues)

Tools (parallel):

  1. Bashls && ls src && ls src/Core → project layout (Core, Ps, Potion, Upload, Upload.GlobalConnect, WebApi, …)
  2. Grep av1|Av1|AV1 case-insensitive → 9 files, of which the production ones are src/Core/Config.fs, src/Core/Domain/GlobalConnectActions.fs, src/Core/Domain/ActionContext.fs

Next tool: Bashgrep -n -i "av1" on those three files:

src/Core/Config.fs:570:        let EnableAV1Upload = "enableAV1Upload"
src/Core/Domain/GlobalConnectActions.fs:227:        | MediaPropertiesV2 p -> p.Video.Codec <> "av1" || ctx.EnableAV1Upload()
src/Core/Domain/ActionContext.fs:32:            EnableAV1Upload: unit -> bool
src/Core/Domain/ActionContext.fs:61:                EnableAV1Upload = fun () -> getFeatureFlag ConfigKey.EnableAV1Upload

Next tool: Read src/Core/Domain/GlobalConnectActions.fs (all 651 lines).

Critical finding — isContentSupportedByOrigin at line 225, and its only two call sites:

let isContentSupportedByOrigin (ctx: GlobalConnectActionContext) (file: ContentFile) =
    match file.MediaProperties with
    | MediaPropertiesV2 p -> p.Video.Codec <> "av1" || ctx.EnableAV1Upload()
    | _ -> true
  • line 240 — buildUploadFileActions
  • line 509 — getActiveFiles

It is not applied anywhere in the smil path (buildSmilActions, line 415).

Turn 4 — assistant (tracing the smil path)

Tools (parallel):

  1. Bashgrep -rn "fromCurrentState" src/GlobalConnectActions.fs:454, MediaSetTypes.fs:1323 (definition), GlobalConnectFileUploadActor.fs:223
  2. Bashls -R src/Core/Domain

Next tool: Read src/Core/Domain/MediaSetTypes.fs lines 1200–1420.

Found the suspect filter in GlobalConnectSmil.fromCurrentState (line 1333):

let mediaFiles =
    currentState.Files
    |> Map.filter (fun _ file -> GlobalConnectAccessRestrictions.parse file.File.RemotePath = desiredState.GeoRestriction)
    |> Map.filter (fun fileRef _ -> desiredState.Content |> ContentSet.getFiles |> Map.keys |> Seq.contains fileRef)
    |> Map.filter (fun _ file -> file.RemoteState.State = DistributionState.Completed)

Turns 5–14 — assistant (confirming the mechanism)

A long read-only sweep to confirm FileRef is bit-rate-derived and that nothing else filters the stale entry. Tool calls in order:

# Tool Target What it established
1 Bash/Grep awaitS3Smil, awaitS3Files call sites test helper locations
2 Read tests/IsolatedTests/Utils.fs (248 lines) getExpectedSmilContent, tryGetSmilFilePath pick the max-version smil
3 Grep type ContentFile, type FileRef MediaSetTypes.fs:281, :456
4 Read MediaSetTypes.fs 230–630 FileRef = { PartId; QualityId } — no version, no filename
5 Bash sed 800,900 + upload actor 190–260 GlobalConnectFile carries TranscodingVersion
6 Bash git log -S"isContentSupportedByOrigin" added in 3124a744f "Add feature toggle for upload of AV1 files (#3858)"
7 Bash all isContentSupportedByOrigin / EnableAV1Upload usages confirms only 2 call sites, smil not covered
8 Bash grep -i av1 -B30 -A30 unit tests GlobalConnectActionsTests.fs:105 sets EnableAV1Upload = fun () -> true
9 Bash sed 1100,1200 MediaSetTypes createMediaFileElements, GlobalConnectPathBase
10 Bash grep QualityId.create|rungName PsJobCreation.fs:366: QualityId = QualityId.create details.BitRate
11 Read PsTests.fs 255–400 test publishes bitRate: ndx+1 → bit rates 1..5 both times
12 Read Config.fs 510–600 the getFeatureFlag / Unchecked.defaultof TODO
13 Read MediaSetState.fs (387 lines) AssignedGlobalConnectFile does Map.add fileRef fileState — overwrite keyed on FileRef
14 Read MediaSetActions.fs, ContentActions.fs, ActionContext.fs desired-state assignment path
15 Bash PsTypes.fs 555–760, PsPlaybackEvents.fs 150–300 PsFilesState.update, quality strings
16 Bash PsUtils.fs createFileName filename = basePart_bitRate.ext
17 Read MediaSetTypes.fs 296–303 ContentFile.transcodingVersion helper already exists
18 Bash unit-test fromCurrentState call sites GlobalConnectActionsTests:148, MediaSetTests:336, SmilFileTests:193,203

Conclusion reached: bit rate 1 is reused across both transcodings, so the AV1 file's FileRef collides with the previous transcoding's file. Because the AV1 file is never uploaded, the current-state entry under that FileRef still holds the old file — and the smil filter, matching on FileRef only, lets it through.

Turn 15 — assistant (first fix attempt)

I've found the bug. Let me apply the fix.

Edit src/Core/Domain/MediaSetTypes.fs — filename-based matching:

let desiredFiles = desiredState.Content |> ContentSet.getFiles
let isDesiredFile fileRef (file: GlobalConnectFileState) =
    match desiredFiles |> Map.tryFind fileRef with
    | Some desiredFile ->
        let remoteFileName = file.File.RemotePath.Value.Split [| '/' |] |> Seq.last
        remoteFileName = normalizeGlobalConnectFileName desiredFile.FileName.Value
    | None -> false

Bash dotnet build src/Core/Core.fsprojBuild succeeded. 0 Warning(s) 0 Error(s)

Turn 16 — assistant (unit tests)

Core builds. Now let me verify the existing unit tests still pass, since the smil logic is widely used.

  • dotnet test tests/UnitTestsZero tests ran, exit 5 (xunit.v3 in-process runner doesn't work through dotnet test here)
  • Ran UnitTests.exe directly; output drowned in Akka logs, so redirected to a file and grepped

6 failures, including one clearly caused by the edit:

Nrk.Oddjob.UnitTests.SmilFileTests.Smil fromCurrentState with one completed and one deprecated file [FAIL]
  Assert.Equal() Failure: Strings differ
  Expected: ···"ding="utf-8"?><smil><body><switch><videosrc="abc_i"···
  Actual:   ···"ding="utf-8"?><smil><body/></smil>"

Read tests/UnitTests/SmilFileTests.fs 280–360: the test's current-state remote path is assets/no/open/abc_ID360.mp4 while the desired FileName is abc_ID360.mp4 — case differs, so the raw comparison failed.

Turn 17 — assistant (edit rejected, then approved)

Edit proposed: normalize both sides of the filename comparison.

Rejected by the user.

Turn 18 — user

Yes, make this change

Turn 19 — assistant

Edit applied:

normalizeGlobalConnectFileName remoteFileName = normalizeGlobalConnectFileName desiredFile.FileName.Value

Now let me check whether the other failures pre-exist my change, by stashing and running the baseline.

  • git stash + rebuild + run → 1 failure only, and a different one: GlobalConnect PublishSubtitles job for unchanged subtitles generates events — flaky Akka timing.
  • git stash pop, rebuild, rerun → 5 failures, all in GlobalConnectUploadTests:
GlobalConnect PublishMediaSet job for completed file with missing file reference generates events
GlobalConnect SetGeoRestriction job with one file generates events
GlobalConnect SetGeoRestriction job with unchanged geolocation generates events
GlobalConnect SetGeoRestriction job with part generates events
GlobalConnect SetGeoRestriction job with part and two files generates events

Those 5 are real regressions from my change. Let me examine.

Failure detail:

System.ArgumentException : The index was outside the range of elements in the list. (Parameter 'n')
  at Nrk.Oddjob.UnitTests.Upload.Helpers.verifyGlobalConnectSmilContent(...)

i.e. the smil came out empty — those tests build current-state files whose remote path doesn't correspond to the desired filename.

Turn 20 — assistant (second, final fix)

The filename comparison is too fragile. The real signal is the transcoding version, which GlobalConnectFile already carries. Let me use that instead.

Edit src/Core/Domain/MediaSetTypes.fs:

let desiredFiles = desiredState.Content |> ContentSet.getFiles
// Matching on file reference alone is not enough: a retranscoding may reuse the same quality (bit rate) for a file
// that is never uploaded, e.g. because its codec is not supported by the origin. The current state then still holds
// the file from the previous transcoding under that reference, and that stale file must not be listed in the smil.
let isDesiredFile fileRef (file: GlobalConnectFileState) =
    match desiredFiles |> Map.tryFind fileRef with
    | Some desiredFile -> file.File.TranscodingVersion >= ContentFile.transcodingVersion desiredFile
    | None -> false
let mediaFiles =
    currentState.Files
    |> Map.filter (fun _ file -> GlobalConnectAccessRestrictions.parse file.File.RemotePath = desiredState.GeoRestriction)
    |> Map.filter isDesiredFile
    |> Map.filter (fun _ file -> file.RemoteState.State = DistributionState.Completed)

Rebuild + run unit tests → EXIT=0, no failures.

Turn 21 — assistant (bringing up the isolated environment)

All unit tests pass. Now let me try running the actual isolated test — it needs the docker services.

  • docker ps → 11 containers up ~2 hours, including localservices-oddjob-1 (healthy)
  • Found localservices/docker-compose-isolated-tests.yaml (includes base compose + isolated-tests/isolated-tests-overrides.yaml)
  • One grep -rn --include=* over the repo ran past 120 s and was auto-backgrounded; cancelled with TaskStop
  • Checked build secrets — NRK_GITHUB_TOKEN, PHOBOS_NUGET_USERNAME, PHOBOS_NUGET_PASSWORD, ODADISTRIBUSJON_VOLUME_LOCATION, POTION_VOLUME_LOCATION — all SET

Everything's available. Let me rebuild the oddjob container with the fix and restart it.

  • docker compose build oddjobEXIT=0, image built
  • docker compose up -d oddjob → failed: service "init-mssql-db" didn't complete successfully: exit 1
  • docker logs localservices-init-mssql-db-1The operation failed because an index or statistics with name 'IX_MediaSetStatuses_ActivationTime' already exists

The init job fails only because the DB is already initialized. Let me start oddjob without re-running dependencies.

  • docker compose up -d --no-deps oddjob → started
  • Monitor on container logs → Cluster Node [akka.tcp://Oddjob@8e463e559755:1970] … to [Up]

Turn 22 — assistant (running the target test)

The node is Up. Let me run the failing test.

  • dotnet test tests/IsolatedTests --filter-method …Zero tests ran
  • ./IsolatedTests.exe --filter-method …error: unknown option: --filter-method
  • ./IsolatedTests.exe --help → correct syntax is the query filter -filter "/asm/ns/class/method"
  • ./IsolatedTests.exe -filter "/*/*/*/*retranscoding*"
IsolatedTests  Total: 2, Errors: 0, Failed: 0, Skipped: 0, Not Run: 0, Time: 31.761s

Both theory cases pass. Let me confirm this test actually failed before the fix, so I know the fix is what made it pass.

Turn 23 — assistant (baseline confirmation)

  • git stash → fix reverted
  • Rebuilt and restarted the container from the stashed (unfixed) source
  • Monitor → node Up
  • Ran the same filter →
PsTests+PsTranscodingTests.When a program gets retranscoding … (mediaSource: Archive) [FAIL]
PsTests+PsTranscodingTests.When a program gets retranscoding … (mediaSource: DropFolder) [FAIL]
IsolatedTests  Total: 2, Errors: 0, Failed: 2, Skipped: 0, Not Run: 0, Time: 25.138s

Failure detail — exactly the predicted symptom:

Assert.Equal() Failure: Strings differ
Expected: ···"deo src="idxf52097762cc_170001_2.mp4" language="no"···
Actual:   ···"deo src="idxf52097762cc_1.mp4" language="nor" audi"···

Confirmed: fails without the fix, passes with it.

  • git stash pop, rebuild container, Monitor → node Up
  • Rebuilt + reran unit tests → EXIT=0

Turn 24 — assistant (full isolated suite)

./IsolatedTests.exe (all 64 tests) →

IsolatedTests  Total: 64, Errors: 0, Failed: 8, Skipped: 0, Not Run: 0, Time: 139.461s

Inspecting the 8:

ConnectionsQuotaExceeded for namespace sbemulatorns … (QuotaExceeded)
No playback message with programId=VMSG67958370

These look like Service Bus emulator connection-quota exhaustion from 64 parallel tests, not smil errors. Let me verify by running just the transcoding class.

Bash ./IsolatedTests.exe -class "PsTests+PsTranscodingTests"rejected by the user.

Turn 25 — user

There were some flaky tests. I manually re-run them, and they all passed.

Turn 26 — assistant (final summary)

Reported the root cause, the fix, the rejected filename approach and why, and the verification table. Flagged the unrelated getFeatureFlag / Unchecked.defaultof<'a> TODO in Config.fs:544 as a separate latent issue (a flag whose intended default is true would silently read false), explicitly noting it was not changed.

Turn 27 — user

Can you save our conversation from this session in a separate file, please.

Turn 28 — assistant

Wrote av1-overlapping-bitrate-session.md — a technical write-up rather than a transcript. Flagged that the file is untracked in the working tree, and offered to move or ignore it; also offered to redo it as a literal transcript.

Turn 29 — user

Also save the actual transcript in av1-overlapping-bitrate-transcript.md

Turn 30 — assistant

This file.


Net change from the whole session

One file, nine lines added, one replaced:

src/Core/Domain/MediaSetTypes.fs | 10 +++++++++-
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment