Repository navigation
feat(media-server): capcodec H.264 transcode behind a flag - #2446
Conversation
ffmpeg decodes to raw yuv420p, capcodec encodes, and a remux adds audio. The path stays off unless CAP_MEDIA_VIDEO_ENCODER=capcodec. Job CRF and preset apply unless CAPCODEC_CRF or CAPCODEC_PRESET is set. Benchmarks against x264 veryfast are in capcodec-benchmarks.md.
|
hey @greptileai please rereview |
| ): CapcodecOptions | null { | ||
| if (env.CAP_MEDIA_VIDEO_ENCODER !== "capcodec") return null; | ||
| return { | ||
| binary: env.CAPCODEC_BIN?.trim() || "capcodec", |
There was a problem hiding this comment.
Shipped images lack the encoder
Enabling CAP_MEDIA_VIDEO_ENCODER=capcodec in either shipped media-server image selects an executable that the image does not contain. Both Dockerfiles install FFmpeg and copy the application, but neither supplies capcodec. Without a separately supplied executable, video jobs that need conversion fail at startup. Include a pinned executable in the images, or document the deployment step that supplies CAPCODEC_BIN.
Knowledge Base Used: Media-server runtime service
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/media-server/src/lib/capcodec-encoder.ts
Line: 81
Comment:
**Shipped images lack the encoder**
Enabling `CAP_MEDIA_VIDEO_ENCODER=capcodec` in either shipped media-server image selects an executable that the image does not contain. Both Dockerfiles install FFmpeg and copy the application, but neither supplies `capcodec`. Without a separately supplied executable, video jobs that need conversion fail at startup. Include a pinned executable in the images, or document the deployment step that supplies `CAPCODEC_BIN`.
**Knowledge Base Used:** [Media-server runtime service](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/media-server-and-web-cluster.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| const encoder = registerSubprocess( | ||
| spawn({ |
There was a problem hiding this comment.
Failed starts skip decoder cleanup
If the encoder cannot start—for example, because CAPCODEC_BIN names a missing executable—the decoder has already started, but execution never reaches the try or abort listener. Nothing on this error path stops or unregisters the decoder. This can leave FFmpeg running without a consumer and stale entries in the process registry. Move encoder startup inside a cleanup-protected block so every failure stops the decoder.
Knowledge Base Used: Media-server runtime service
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/media-server/src/lib/capcodec-encoder.ts
Line: 284-285
Comment:
**Failed starts skip decoder cleanup**
If the encoder cannot start—for example, because `CAPCODEC_BIN` names a missing executable—the decoder has already started, but execution never reaches the `try` or abort listener. Nothing on this error path stops or unregisters the decoder. This can leave FFmpeg running without a consumer and stale entries in the process registry. Move encoder startup inside a cleanup-protected block so every failure stops the decoder.
**Knowledge Base Used:** [Media-server runtime service](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/media-server-and-web-cluster.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| abortSignal: controller.signal, | ||
| }), | ||
| processTimeoutMs, | ||
| async () => controller.abort(), |
There was a problem hiding this comment.
Timeout cleanup returns too early
The timeout callback only calls controller.abort(); it does not wait for either process to exit. Their abort handler starts terminateProcess without awaiting it, so withTimeout returns and videoOnly.cleanup() runs while encoding can still be active. Timed-out jobs can keep using CPU after their job slot is released, and the output file can be deleted before its writer exits. Keep the encode promise and await its cleanup after aborting, before deleting the file or returning.
Knowledge Base Used: Media-server runtime service
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/media-server/src/lib/media-video.ts
Line: 1729
Comment:
**Timeout cleanup returns too early**
The timeout callback only calls `controller.abort()`; it does not wait for either process to exit. Their abort handler starts `terminateProcess` without awaiting it, so `withTimeout` returns and `videoOnly.cleanup()` runs while encoding can still be active. Timed-out jobs can keep using CPU after their job slot is released, and the output file can be deleted before its writer exits. Keep the encode promise and await its cleanup after aborting, before deleting the file or returning.
**Knowledge Base Used:** [Media-server runtime service](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/media-server-and-web-cluster.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.…fails The media-server images do not ship capcodec. Jobs check CAPCODEC_BIN before ffmpeg starts, and capcodec.md describes the mount. A failed encoder start stops the decoder, and a timeout waits for both processes to exit before deleting the output.
|
hey @greptileai please rereview |
| job: CapcodecEncodeJob, | ||
| ): Promise<void> { | ||
| if (job.abortSignal?.aborted) throw cancelled(); | ||
| await assertCapcodecBinary(job.options.binary); |
There was a problem hiding this comment.
If a job is cancelled while assertCapcodecBinary awaits the file check, encodeVideoWithCapcodec still starts both processes. The abort listener is added after the signal has fired, and the next cancellation check waits until both stderr streams close. The job can encode the whole video before stopping, and timeout cleanup now waits for that work to finish.
Recheck job.abortSignal.aborted immediately after the binary check, before starting either process.
| await assertCapcodecBinary(job.options.binary); | |
| await assertCapcodecBinary(job.options.binary); | |
| if (job.abortSignal?.aborted) throw cancelled(); |
Knowledge Base Used: Media-server runtime service
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/media-server/src/lib/capcodec-encoder.ts
Line: 290
Comment:
**Cancelled jobs keep encoding**
If a job is cancelled while `assertCapcodecBinary` awaits the file check, `encodeVideoWithCapcodec` still starts both processes. The abort listener is added after the signal has fired, and the next cancellation check waits until both stderr streams close. The job can encode the whole video before stopping, and timeout cleanup now waits for that work to finish.
Recheck `job.abortSignal.aborted` immediately after the binary check, before starting either process.
```suggestion
await assertCapcodecBinary(job.options.binary);
if (job.abortSignal?.aborted) throw cancelled();
```
**Knowledge Base Used:** [Media-server runtime service](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/media-server-and-web-cluster.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.A cancel during the binary check used to launch ffmpeg and capcodec, because the abort listener was attached only after both had started.
|
hey @greptileai please rereview |
The Tov encoder lived only on the build machine. This adds the main tree, a bundle of the other branches, and keeps Biome from linting it.
|
hey @greptileai please rereview |
CodeQL treated the corpus fixtures as application JavaScript. The video page now takes its file URL from the generator, and the wiki preview writes link text as text.
|
hey @greptileai please rereview |
| w.u32(this.data.length + 8) | ||
| w.fourcc("mdat") | ||
| } | ||
| w.bytes(this.data, 0, this.data.length) |
There was a problem hiding this comment.
Long conversions exhaust memory
Mp4Muxer keeps every encoded byte in data, then copies the whole movie into another buffer in progressive(). The media server always selects this path through its .mp4 temporary file. Long recordings can therefore use gigabytes of memory and fail before the output is written. Write samples to disk as they arrive, or use the existing fragmented output before the final remux.
Knowledge Base Used: Media delivery services
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/src/mux/mp4.tov
Line: 389
Comment:
**Long conversions exhaust memory**
`Mp4Muxer` keeps every encoded byte in `data`, then copies the whole movie into another buffer in `progressive()`. The media server always selects this path through its `.mp4` temporary file. Long recordings can therefore use gigabytes of memory and fail before the output is written. Write samples to disk as they arrive, or use the existing fragmented output before the final remux.
**Knowledge Base Used:** [Media delivery services](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/media-delivery-services.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| w.fourcc("nclx") | ||
| w.u16(1) | ||
| w.u16(1) | ||
| w.u16(1) | ||
| w.u8(0) |
There was a problem hiding this comment.
Converted videos show wrong colors
writeStsd() labels every output as BT.709 with limited range, and writeSps() makes the same assumption. The media server accepts other color formats, but its decode filter does not convert their color matrix to BT.709. A BT.601 source therefore keeps its original pixel values with different color labels, so playback shows shifted colors. Convert incoming frames to BT.709 or carry the source's color settings into both writers.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/src/mux/mp4.tov
Line: 175-179
Comment:
**Converted videos show wrong colors**
`writeStsd()` labels every output as BT.709 with limited range, and `writeSps()` makes the same assumption. The media server accepts other color formats, but its decode filter does not convert their color matrix to BT.709. A BT.601 source therefore keeps its original pixel values with different color labels, so playback shows shifted colors. Convert incoming frames to BT.709 or carry the source's color settings into both writers.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| jobs.append((f"x264_t{t}", x264_cmd(src, a.x264_crf, mode, 0 if t > 1 else 1, work / "x.mp4", | ||
| a.keyint1))) |
There was a problem hiding this comment.
Thread comparisons are mislabeled
The four-thread comparison passes -threads 0 to x264, while capcodec receives --threads 4. Every requested count above one takes this same automatic x264 setting. The report still labels both results with the requested count, so it does not measure equal thread limits. Pass t to x264_cmd() or label x264 as using automatic threading.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/speedcmp.py
Line: 344-345
Comment:
**Thread comparisons are mislabeled**
The four-thread comparison passes `-threads 0` to x264, while capcodec receives `--threads 4`. Every requested count above one takes this same automatic x264 setting. The report still labels both results with the requested count, so it does not measure equal thread limits. Pass `t` to `x264_cmd()` or label x264 as using automatic threading.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| import { processVideo } from "/workspace/apps/media-server/src/lib/media-video"; | ||
| import { probeVideoFile } from "/workspace/apps/media-server/src/lib/media-probe"; |
There was a problem hiding this comment.
Integration driver cannot load
media-server-driver.ts imports from /workspace instead of this checkout. If the checkout lives elsewhere, running the supplied driver fails before it can probe or convert a video. Use relative imports so the driver measures the media-server code shipped alongside it.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/integration/media-server-driver.ts
Line: 1-2
Comment:
**Integration driver cannot load**
`media-server-driver.ts` imports from `/workspace` instead of this checkout. If the checkout lives elsewhere, running the supplied driver fails before it can probe or convert a video. Use relative imports so the driver measures the media-server code shipped alongside it.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.|
|
||
|
|
||
| def committed_best() -> dict | None: | ||
| r = subprocess.run(["git", "-C", str(ROOT), "show", "HEAD:bench/best.json"], capture_output=True, text=True) |
There was a problem hiding this comment.
Smoke check uses edited baseline
committed_best() still reads HEAD:bench/best.json, but the committed file now lives at capcodec/bench/best.json. Running Git from capcodec/ does not change that tree path. The lookup fails and reads the working copy instead, so an uncommitted baseline edit can hide a regression. Read the correct committed path while retaining support for a restored standalone repository.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/bench.py
Line: 21
Comment:
**Smoke check uses edited baseline**
`committed_best()` still reads `HEAD:bench/best.json`, but the committed file now lives at `capcodec/bench/best.json`. Running Git from `capcodec/` does not change that tree path. The lookup fails and reads the working copy instead, so an uncommitted baseline edit can hide a regression. Read the correct committed path while retaining support for a restored standalone repository.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| if s is None: | ||
| msgs.append(f"{GATE_ENCODER} not run; gate checks decode only") | ||
| return ok, msgs |
There was a problem hiding this comment.
A missing capcodec-medium binary is skipped, then gate() returns success if the remaining x264 runs pass. Developers can therefore get a passing encoder check without testing capcodec at all. Require both the smoke encoder and its reference before accepting the run.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/harness/runner.py
Line: 639-641
Comment:
**Smoke passes without capcodec**
A missing `capcodec-medium` binary is skipped, then `gate()` returns success if the remaining x264 runs pass. Developers can therefore get a passing encoder check without testing capcodec at all. Require both the smoke encoder and its reference before accepting the run.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| inbox: '<path d="M3 13l3-8h12l3 8v6H3z"/><path d="M3 13h5l1 3h6l1-3h5"/>', | ||
| user: '<circle cx="12" cy="8" r="4"/><path d="M4 21c1-4 4-6 8-6s7 2 8 6"/>', |
There was a problem hiding this comment.
JavaScript quotes break repository rule
The new JavaScript uses single-quoted strings, contrary to the repository guide's requirement for double-quoted JS/TS strings. This appears throughout board.js and also in workbench.js. Format these files before merging; excluding capcodec from Biome does not remove the repository requirement.
Context Used: AGENTS.md (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/corpus/pages/common/board.js
Line: 4-5
Comment:
**JavaScript quotes break repository rule**
The new JavaScript uses single-quoted strings, contrary to the repository guide's requirement for double-quoted JS/TS strings. This appears throughout `board.js` and also in `workbench.js`. Format these files before merging; excluding `capcodec` from Biome does not remove the repository requirement.
**Context Used:** AGENTS.md ([source](https://github.com/capsoftware/cap/blob/main/AGENTS.md))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
These single quotes are the form Biome emits. quoteStyle is double, and biome ci rewrites "<path d=\"M3\"/>" back to '<path d="M3"/>' because the string contains a double quote. Every remaining single-quoted literal in the capcodec scripts is an SVG or HTML fragment in that situation. Escaping them would fail the format check.
There was a problem hiding this comment.
You're right. Biome's quoteStyle: "double" is a preference, not an unconditional requirement: for literals containing double quotes, such as these SVG/HTML fragments, it emits single quotes to avoid escaping, and biome ci accepts that output.
The quote finding should therefore be withdrawn; no source change is needed. The related “exclude all of capcodec” concern was also overstated: the configuration excludes only specific non-JS capcodec artifacts, while the JavaScript files remain covered by Biome.
Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.
Decode into limited-range BT.709 before encode, and write a fragmented MP4 so a long transcode flushes each GOP. The bench gate requires both encoders, the baseline lookup works inside this repo, and the speed report states that x264's higher thread count is automatic.
|
hey @greptileai please rereview |
| w.u32(this.data.length + 8) | ||
| w.fourcc("mdat") | ||
| } | ||
| w.bytes(this.data, 0, this.data.length) |
There was a problem hiding this comment.
Long conversions exhaust memory
The media-server always selects progressive MP4 output. Mp4Muxer keeps the entire encoded video in data, then copies it into another full buffer before writing. Long recordings can use more than twice their encoded size in RAM and exhaust the container's memory.
Write samples to disk as they arrive, or use fragmented output for the intermediate file.
Knowledge Base Used:
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/src/mux/mp4.tov
Line: 389
Comment:
**Long conversions exhaust memory**
The media-server always selects progressive MP4 output. `Mp4Muxer` keeps the entire encoded video in `data`, then copies it into another full buffer before writing. Long recordings can use more than twice their encoded size in RAM and exhaust the container's memory.
Write samples to disk as they arrive, or use fragmented output for the intermediate file.
**Knowledge Base Used:**
- [Media delivery services](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/media-delivery-services.md)
- [Media-server runtime service](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/media-server-and-web-cluster.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| const c = w.begin("colr") | ||
| w.fourcc("nclx") | ||
| w.u16(1) | ||
| w.u16(1) | ||
| w.u16(1) | ||
| w.u8(0) |
There was a problem hiding this comment.
Converted videos change colors
writeStsd always labels the output as BT.709 with limited range. The media-server decoder only scales and requests yuv420p; it does not convert other color matrices to BT.709. A BT.601 source that needs conversion is therefore encoded with the wrong color label, so players show shifted colors.
Convert the raw frames to the declared color settings or carry the source settings into the encoder.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/src/mux/mp4.tov
Line: 174-179
Comment:
**Converted videos change colors**
`writeStsd` always labels the output as BT.709 with limited range. The media-server decoder only scales and requests `yuv420p`; it does not convert other color matrices to BT.709. A BT.601 source that needs conversion is therefore encoded with the wrong color label, so players show shifted colors.
Convert the raw frames to the declared color settings or carry the source settings into the encoder.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| def __enter__(self): | ||
| if self.enabled: | ||
| for _ in range(20): | ||
| new = [p for p in freezable() if p not in self.stopped] | ||
| if not new: | ||
| break | ||
| self.stop(new) | ||
| time.sleep(0.05) |
There was a problem hiding this comment.
Cancelled benchmarks leave jobs frozen
Cancelling speedcmp.py during Quiet.__enter__ can leave unrelated processes stopped. Startup already sends SIGSTOP, but __exit__ does not run when __enter__ raises. The signal handler cannot resume them either: timed still holds the lock that thaw_leftovers tries to acquire.
Catch startup failures inside __enter__ and resume every process already stopped.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/speedcmp.py
Line: 174-181
Comment:
**Cancelled benchmarks leave jobs frozen**
Cancelling `speedcmp.py` during `Quiet.__enter__` can leave unrelated processes stopped. Startup already sends `SIGSTOP`, but `__exit__` does not run when `__enter__` raises. The signal handler cannot resume them either: `timed` still holds the lock that `thaw_leftovers` tries to acquire.
Catch startup failures inside `__enter__` and resume every process already stopped.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| if s is None: | ||
| msgs.append(f"{GATE_ENCODER} not run; gate checks decode only") | ||
| return ok, msgs |
There was a problem hiding this comment.
The smoke check succeeds when capcodec-medium was never run. A missing binary removes its adapter, and this branch returns the still-true ok value. Missing reference quality data also does not fail the check. Developers can get a successful result without testing the intended encoder.
Require the target encoder, reference encoder, and required comparison results before reporting success.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/harness/runner.py
Line: 639-641
Comment:
**Smoke checks skip the encoder**
The smoke check succeeds when `capcodec-medium` was never run. A missing binary removes its adapter, and this branch returns the still-true `ok` value. Missing reference quality data also does not fail the check. Developers can get a successful result without testing the intended encoder.
Require the target encoder, reference encoder, and required comparison results before reporting success.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| "speed_wall_fps_median": statistics.median([r["speed_wall_fps"] for r in sr if r.get("speed_wall_fps")]) if sr else None, | ||
| "decode_failures": sum(1 for r in er if r.get("decode_ffmpeg_ok") is False or r.get("decode_jm_ok") is False | ||
| or r.get("recon_match") is False or r.get("jm_match") is False), | ||
| "errors": sum(1 for r in rows if r["encoder"] == e and r.get("error")), |
There was a problem hiding this comment.
measure returns metrics_error when a quality measurement fails, but summarize only counts error and decode failures. If decoding succeeds and the measurement process fails, the smoke check can pass without a usable quality comparison.
Count metrics_error as a failed check so developers do not miss broken measurements.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/harness/runner.py
Line: 591
Comment:
**Failed quality checks pass**
`measure` returns `metrics_error` when a quality measurement fails, but `summarize` only counts `error` and decode failures. If decoding succeeds and the measurement process fails, the smoke check can pass without a usable quality comparison.
Count `metrics_error` as a failed check so developers do not miss broken measurements.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| jobs.append((f"x264_t{t}", x264_cmd(src, a.x264_crf, mode, 0 if t > 1 else 1, work / "x.mp4", | ||
| a.keyint1))) |
There was a problem hiding this comment.
Speed reports mislabel thread counts
Every requested thread count above one runs x264 with -threads 0, while capcodec receives the requested count. The report still labels both results with that count. For example, --threads 4 compares four capcodec threads with x264's automatic thread count, so readers cannot use the labels to compare how the encoders scale.
Pass t to both encoders or label the automatic comparison accurately.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/speedcmp.py
Line: 344-345
Comment:
**Speed reports mislabel thread counts**
Every requested thread count above one runs x264 with `-threads 0`, while capcodec receives the requested count. The report still labels both results with that count. For example, `--threads 4` compares four capcodec threads with x264's automatic thread count, so readers cannot use the labels to compare how the encoders scale.
Pass `t` to both encoders or label the automatic comparison accurately.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| import { processVideo } from "/workspace/apps/media-server/src/lib/media-video"; | ||
| import { probeVideoFile } from "/workspace/apps/media-server/src/lib/media-probe"; |
There was a problem hiding this comment.
The integration driver imports the media-server from absolute /workspace paths. Running its advertised command from a checkout elsewhere fails before reading the input.
Use imports relative to this file so developers can run the copied driver from their own checkout.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/integration/media-server-driver.ts
Line: 1-2
Comment:
**Driver needs a fixed checkout**
The integration driver imports the media-server from absolute `/workspace` paths. Running its advertised command from a checkout elsewhere fails before reading the input.
Use imports relative to this file so developers can run the copied driver from their own checkout.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| How to reproduce (from the `capcodec/` directory in this repository): | ||
|
|
||
| - Quality: `CAPCODEC_BIN_UNCHECKED=<binary> python3 bench/bench.py standard --quality-only --encoders capcodec-medium,capcodec-live,capcodec-live-zerolatency,x264-veryfast,x264-veryfast-zerolatency --out <dir>` (1080p, 10 s per clip; code_4k is scaled to 1080p here). capcodec's CRF ladder runs 20-44 so its VMAF range covers x264's CRF 18-33; the overlap column shows how much of the two curves BD-rate compares (it was 15-24% on screen clips with the old 20-36 ladder). | ||
| - Speed: `bench/lane.sh start`, then `bench/lane.sh run "python3 bench/speedcmp.py --binary <binary> --clips all --modes medium,live,zerolatency --retime bench/out/speedcmp-fff504d-v2 --out <dir>"`. The rerun reuses the CRF that matched x264 CRF 23 (bitstreams are unchanged, so the match stands). 5 shuffled, interleaved rounds at 1 and 4 threads; every other process is stopped for each timed run (about 690 processes stopped, frozen median). code_4k runs at native 4K for 5 s. Output: `bench/out/speedcmp-00fecf7`. |
There was a problem hiding this comment.
Reproduction needs missing results
The speed command requires bench/out/speedcmp-fff504d-v2/results.json, but that output directory is excluded from the repository. speedcmp.py reads it unconditionally when --retime is supplied, so the command fails in a fresh checkout. The same command appears in SCOREBOARD.md.
Remove --retime from the fresh-run instructions or supply the saved results separately.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/media-server/capcodec-benchmarks.md
Line: 22-25
Comment:
**Reproduction needs missing results**
The speed command requires `bench/out/speedcmp-fff504d-v2/results.json`, but that output directory is excluded from the repository. `speedcmp.py` reads it unconditionally when `--retime` is supplied, so the command fails in a fresh checkout. The same command appears in `SCOREBOARD.md`.
Remove `--retime` from the fresh-run instructions or supply the saved results separately.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| "!apps/web/public/gif.worker.js", | ||
| "!packages/ui-solid/src/auto-imports.d.ts" | ||
| "!packages/ui-solid/src/auto-imports.d.ts", | ||
| "!capcodec" |
There was a problem hiding this comment.
New files bypass required checks
Excluding all of capcodec from Biome bypasses the repository guide's directive not to override the root Biome rules locally. The new JavaScript also violates its double-quote requirement, for example in dashboard.js.
Keep supported files under the shared checks and fix their formatting instead of excluding the whole directory. This repository requirement must be satisfied before merging.
Context Used: AGENTS.md (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: biome.json
Line: 17
Comment:
**New files bypass required checks**
Excluding all of `capcodec` from Biome bypasses the repository guide's directive not to override the root Biome rules locally. The new JavaScript also violates its double-quote requirement, for example in `dashboard.js`.
Keep supported files under the shared checks and fix their formatting instead of excluding the whole directory. This repository requirement must be satisfied before merging.
**Context Used:** AGENTS.md ([source](https://github.com/capsoftware/cap/blob/main/AGENTS.md))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
|
||
|
|
||
| class FFmpegAdapter(Adapter): | ||
| """An encoder driven through ffmpeg: codec_args(src, params, speed) returns the codec options.""" |
There was a problem hiding this comment.
The added FFmpegAdapter docstring only restates what the class does. The repository guide bans comments that narrate code or paraphrase names and types. The module introductions in generate.py and scenarios.py follow the same pattern, which also appears elsewhere.
Remove this narration and keep comments that explain non-obvious constraints. This repository requirement must be satisfied before merging.
Context Used: AGENTS.md (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/harness/adapters/base.py
Line: 83
Comment:
**Comments repeat the code**
The added `FFmpegAdapter` docstring only restates what the class does. The repository guide bans comments that narrate code or paraphrase names and types. The module introductions in `generate.py` and `scenarios.py` follow the same pattern, which also appears elsewhere.
Remove this narration and keep comments that explain non-obvious constraints. This repository requirement must be satisfied before merging.
**Context Used:** AGENTS.md ([source](https://github.com/capsoftware/cap/blob/main/AGENTS.md))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
A cancelled speed run resumes processes it already stopped. The smoke gate needs both encoders and a BD-rate, and a failed quality measurement fails the gate. Biome now formats the capcodec scripts it understands.
|
hey @greptileai please rereview |
| continue; | ||
| } | ||
| } | ||
| const sm = (lang === "py" ? /^[rRbBuUfF]{0,2}("|")/ : /^(\"|")/).exec(rest); |
There was a problem hiding this comment.
Single-quoted strings lose their colors
The formatting change removes single quotes from both string-matching expressions in tokenize(). Python strings such as 'Match' and C character literals now fall through as ordinary code, so regenerated benchmark clips show them in the wrong colors.
Restore the single-quote alternatives. The double-quote rule applies to JavaScript string literals, not characters matched by a regular expression.
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/corpus/pages/common/editor.js
Line: 143
Comment:
**Single-quoted strings lose their colors**
The formatting change removes single quotes from both string-matching expressions in `tokenize()`. Python strings such as `'Match'` and C character literals now fall through as ordinary code, so regenerated benchmark clips show them in the wrong colors.
Restore the single-quote alternatives. The double-quote rule applies to JavaScript string literals, not characters matched by a regular expression.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
hey @greptileai please rereview |
| const sm = (lang === "py" ? /^[rRbBuUfF]{0,2}("|")/ : /^("|")/).exec( | ||
| rest, | ||
| ); |
There was a problem hiding this comment.
Single-quoted strings lose their colors
The changed tokenize regex matches " twice and no longer matches '. Single-quoted Python strings and C character literals now appear as ordinary text or names. This changes the editor and minimap colors in regenerated benchmark clips.
Restore the single-quote alternative in both branches. Quotes inside a regex are not JavaScript string delimiters.
| const sm = (lang === "py" ? /^[rRbBuUfF]{0,2}("|")/ : /^("|")/).exec( | |
| rest, | |
| ); | |
| const sm = (lang === "py" ? /^[rRbBuUfF]{0,2}("|')/ : /^("|')/).exec( | |
| rest, | |
| ); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/corpus/pages/common/editor.js
Line: 157-159
Comment:
**Single-quoted strings lose their colors**
The changed `tokenize` regex matches `"` twice and no longer matches `'`. Single-quoted Python strings and C character literals now appear as ordinary text or names. This changes the editor and minimap colors in regenerated benchmark clips.
Restore the single-quote alternative in both branches. Quotes inside a regex are not JavaScript string delimiters.
```suggestion
const sm = (lang === "py" ? /^[rRbBuUfF]{0,2}("|')/ : /^("|')/).exec(
rest,
);
```
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| const PY_BUILTINS = new Set( | ||
| "len range isinstance min max sum enumerate zip sorted reversed print super any all map filter iter next abs hash id repr getattr setattr hasattr divmod round".split( | ||
| " ", | ||
| ), | ||
| ); |
There was a problem hiding this comment.
Unused code breaks shared rules
editor.js declares PY_BUILTINS but never reads it. The local n in tokenize() is also unused. These files now fall under the shared Biome checks, and the repository guide requires the recommended lint rules, including unused-variable checks, to be followed.
Remove the unused declarations rather than suppressing the checks. This repository requirement must be satisfied before merging.
Context Used: AGENTS.md (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: capcodec/bench/corpus/pages/common/editor.js
Line: 14-18
Comment:
**Unused code breaks shared rules**
`editor.js` declares `PY_BUILTINS` but never reads it. The local `n` in `tokenize()` is also unused. These files now fall under the shared Biome checks, and the repository guide requires the recommended lint rules, including unused-variable checks, to be followed.
Remove the unused declarations rather than suppressing the checks. This repository requirement must be satisfied before merging.
**Context Used:** AGENTS.md ([source](https://github.com/capsoftware/cap/blob/main/AGENTS.md))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.|
hey @greptileai please rereview |
|
hey @greptileai please rereview |
Flag-gated capcodec path for media-server transcodes. It stays off unless
CAP_MEDIA_VIDEO_ENCODER=capcodec.The published images do not include the capcodec binary. Mount one and set
CAPCODEC_BIN, as described inapps/media-server/capcodec.md. ffmpeg decodes to limited-range BT.709 yuv420p, capcodec writes a fragmented MP4 (flushing each GOP), and a remux adds audio and faststart. The job's CRF and preset are used unlessCAPCODEC_CRForCAPCODEC_PRESETis set (ultrafastmaps to capcodecfast). Encode and mux share one timeout.The encoder source is in
capcodec/.capcodec/capcodec.bundlerestores the other branches. The flag runsmain.Benchmarks against x264 veryfast are in
apps/media-server/capcodec-benchmarks.md. At matched VMAF the measured encoder is faster on all 12 clips, on CPU and wall clock, at 1 and 4 threads. Quality on that bitstream is about even. Concurrent B-frames are the default; full_motion 4-thread wall was retimed to 1.35–1.40× medium and 1.44–1.50× live. The 4-thread x264 timing used automatic threading (-threads 0).Test plan
bun test src/__tests__/lib/capcodec-encoder.test.ts(8 tests)
Confidence Score: 5/5
The PR appears safe to merge; no outstanding findings remain.Summary
Adds an optional capcodec H.264 path while keeping libx264 as the default.
Reviews (10) · Last reviewed commit: "fix: remove unused bench script declarat..." · Reviewed by Greptile