Skip to content

Return state after changes; add obs-record-clip and obs-capture-window - #6

Merged
Tom-R-Main merged 2 commits into
mainfrom
improve/recording-tools
Sep 24, 2026
Merged

Tom-R-Main merged 2 commits into
mainfrom
improve/recording-tools

Conversation

@Tom-R-Main

Copy link
Copy Markdown
Owner

Stacked on #5.

State after changes

  • obs-set-input-settings and obs-create-input now return the input's settings and its size in the program scene. They warn when it still renders at 0×0 after giving capture sources about 750 ms to deliver a first frame. We'd have caught the blank Chrome capture immediately.
  • Optional includeScreenshot adds a 960px JPEG, within the existing size limits.
  • obs-set-scene-item-transform returns the transform OBS actually applied.
  • A failed read-back is reported as a warning, never as a failed change.

obs-record-clip

  • Runs preflight, starts recording and confirms it, and adds chapters at set times; a rejected chapter doesn't abort the take.
  • Always stops, including when waiting fails.
  • Then checks the file:
    • ffprobe: length and number of audio streams
    • ffmpeg volumedetect, when expectSilent is set
  • Capped at 50 s because many clients time tool calls out at 60 s.

obs-capture-window (macOS)

  • Creates or reuses a screen_capture input and selects a display before listing windows or apps. Listing apps without a display crashed OBS.
  • Matches the target in the "[App] Title" list, or by ID.
  • Mutes the capture and clears all six audio tracks, fits it to the canvas, and returns its size.
  • An ambiguous match returns the list of candidates.

Tests: 13 new unit tests, including real ffmpeg-generated silent and tone clips (skipped when ffmpeg is missing). npm run check passes (92 unit, 10 e2e).

Not yet verified against live OBS: both combined tools change OBS state (a new input, a recording), so their live test is waiting on approval. Two untested assumptions: that listing display_uuid items is safe, and that the fit transform centres the way I expect.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Vjn8uBEa4mJshaQU3pFuqX

Tom-R-Main and others added 2 commits September 22, 2026 17:55
obs-set-input-settings and obs-create-input read the input back: its settings,
its size wherever it appears in the program scene, and a warning when it still
renders at 0x0 after capture sources have had ~750 ms to produce a frame. An
optional includeScreenshot adds a bounded 960px JPEG of the input.
obs-set-scene-item-transform returns the transform OBS applied. Read-back
failures are reported as warnings, never as a failed change.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vjn8uBEa4mJshaQU3pFuqX
obs-record-clip runs the preflight, starts recording and waits for OBS to
confirm it, adds chapters at the requested offsets, always stops, then checks
the file with ffprobe (length, audio streams) and ffmpeg volumedetect when
silence is expected. Clips are capped at 50 s because many clients time tool
calls out at 60 s.

obs-capture-window (macOS) creates or reuses a screen_capture input, selects
a display before listing windows or apps (listing apps without one crashed
OBS), matches the target by name or ID, mutes it and clears its audio tracks,
and fits it to the canvas, then returns its size like obs-set-input-settings.

The preflight fake state moves to a shared fixture, and the fake OBS takes a
platform option.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vjn8uBEa4mJshaQU3pFuqX
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-22T22:02:25.220719Z 3495062 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3495062cf3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tools/workflows.ts
Comment on lines +101 to +103
const chapters = [...args.chapters].sort((a, b) => a.atSeconds - b.atSeconds);
for (const chapter of chapters) {
await sleep(Math.max(0, startedAt + chapter.atSeconds * 1000 - Date.now()));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject chapters scheduled after the clip ends

When a chapter's atSeconds exceeds durationSeconds, this sleep waits until the chapter time before reaching the stop logic. Since atSeconds has no upper bound, a nominally short clip can record indefinitely, outlive the MCP client's timeout, and continue consuming disk space; validate every chapter against the requested duration or stop at the duration independently of chapter scheduling.

Useful? React with 👍 / 👎.

Comment thread src/tools/workflows.ts
Comment on lines +71 to +73
const { stderr } = await execFileAsync("ffmpeg", [
"-hide_banner", "-nostats", "-i", outputPath, "-map", "0:a:0", "-af", "volumedetect", "-f", "null", "-",
], { timeout: 60_000 });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Measure every recorded audio stream

When advanced OBS recording produces multiple audio streams, mapping only 0:a:0 checks the first stream and can report a recording as silent even when a later recorded track contains audible audio. The post-recording silence verification should analyze all audio streams, or explicitly fail when any stream exceeds the threshold.

Useful? React with 👍 / 👎.

Comment thread src/tools/workflows.ts
Comment on lines +126 to +128
const problems: string[] = [];
if (inspection.durationSeconds !== undefined && inspection.durationSeconds < args.durationSeconds - 2) {
problems.push(`The file is ${inspection.durationSeconds.toFixed(1)}s, shorter than the requested ${args.durationSeconds}s`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scale the short-file tolerance for short clips

For every requested duration of 2 seconds or less, durationSeconds - 2 is nonpositive, so no nonnegative probed duration can satisfy this condition. A requested 1-second recording that contains only a fraction of a second is therefore reported as verified; use a smaller proportional or bounded tolerance so the tool can detect truncated short clips.

Useful? React with 👍 / 👎.

Comment thread src/tools/workflows.ts
Comment on lines +190 to +192
const type = args.window ? SCK_WINDOW_CAPTURE : SCK_APPLICATION_CAPTURE;
if (!existing) {
await client.sendRequest("CreateInput", {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add reused capture inputs to the requested scene

When inputName already exists as a screen_capture but has no scene item in sceneName, this branch skips creation without adding the existing source to that scene. With the default fit: true, the later GetSceneItemId fails after the source settings and audio state have already been changed; with fit: false, the call reports success even though the requested scene contains no capture. Create a scene item for the reused source when it is absent from the target scene.

Useful? React with 👍 / 👎.

@Tom-R-Main
Tom-R-Main changed the base branch from improve/tool-registry to main September 24, 2026 05:11
@Tom-R-Main
Tom-R-Main merged commit 8fc2d17 into main Sep 24, 2026
4 checks passed
@Tom-R-Main
Tom-R-Main deleted the improve/recording-tools branch September 24, 2026 05:13
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