Skip to content

feat(render): add --vertical output with blur-pad and split-stack lay…#104

Open
wigu8989 wants to merge 6 commits into
browser-use:mainfrom
wigu8989:feature/vertical-render
Open

feat(render): add --vertical output with blur-pad and split-stack lay…#104
wigu8989 wants to merge 6 commits into
browser-use:mainfrom
wigu8989:feature/vertical-render

Conversation

@wigu8989

@wigu8989 wigu8989 commented Jul 7, 2026

Copy link
Copy Markdown

…outs

Adds a 9:16 render path that fits the full frame into a blurred letterboxed canvas by default, or crops+stacks left/right halves for genuine split-screen segments (with optional face-centered crop via per-range split_faces). Also fixes the subtitles filter path on Windows, where backslashes broke libass path parsing.


Summary by cubic

Adds a 9:16 vertical render mode with blur-pad and split-stack layouts, plus Windows fixes for subtitle paths and console encoding. Tracks shared .claude/settings.json, adds local docs (decisions.md, checkpoint-summary.md), and ignores .claude/settings.local.json, .claude/memory/, and local videouse-projects/ outputs.

  • New Features

    • --vertical outputs 1080x1920 (or 720x1280 with --draft), preserving HDR tonemapping and grading.
    • Two layouts: blur_pad fits the full frame over a blurred background; split_stack crops left/right and stacks them; optional split_faces [[x,y],[x,y]] centers faces per panel (set per-range in EDL).
  • Bug Fixes

    • Normalize subtitle file paths to forward slashes on Windows to prevent libass parsing errors.
    • Prevent Windows cp1252 console crashes by replacing unencodable characters in stdout/stderr.

Written for commit 0dbdc03. Summary will update on new commits.

Review in cubic

…outs

Adds a 9:16 render path that fits the full frame into a blurred
letterboxed canvas by default, or crops+stacks left/right halves for
genuine split-screen segments (with optional face-centered crop via
per-range split_faces). Also fixes the subtitles filter path on
Windows, where backslashes broke libass path parsing.

@cubic-dev-ai cubic-dev-ai 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.

2 issues found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="helpers/render.py">

<violation number="1" location="helpers/render.py:224">
P1: The `split_stack` crop calculations use `get_source_dims()` (ffprobe coded width/height), but ffmpeg's filter graph auto-rotates frames by default when display-matrix rotation metadata is present (common in phone footage). This means `[0:v]` may see transposed dimensions while the crop math assumes coded dimensions, producing invalid crop coordinates that target the wrong region or exceed the actual frame bounds. For example, a 1920×1080 clip with rotate=90 becomes 1080×1920 in the graph, yet the right-panel crop is computed starting at x=960 with width≈960 — extending past the 1080-wide rotated frame. To keep the filter graph consistent with ffprobe, pass `-noautorotate` before `-i` in the ffmpeg command.</violation>

<violation number="2" location="helpers/render.py:352">
P2: New EDL fields `layout` and `split_faces` are read from the JSON range objects without validation. A typo in `layout` (e.g. `"split-stack"`) silently falls back to `blur_pad` instead of the intended layout, producing a wrong render with no warning. Malformed `split_faces` values crash the render with an `IndexError` or `TypeError` inside `_panel_crop`. Consider validating `layout` against the known set of layouts and checking that `split_faces` is a list of two `[float, float]` pairs before using it.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread helpers/render.py
pre = f"{tonemap}," if tonemap else ""
if layout == "split_stack":
half_h = h // 2
src_w, src_h = get_source_dims(source)

@cubic-dev-ai cubic-dev-ai Bot Jul 7, 2026

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: The split_stack crop calculations use get_source_dims() (ffprobe coded width/height), but ffmpeg's filter graph auto-rotates frames by default when display-matrix rotation metadata is present (common in phone footage). This means [0:v] may see transposed dimensions while the crop math assumes coded dimensions, producing invalid crop coordinates that target the wrong region or exceed the actual frame bounds. For example, a 1920×1080 clip with rotate=90 becomes 1080×1920 in the graph, yet the right-panel crop is computed starting at x=960 with width≈960 — extending past the 1080-wide rotated frame. To keep the filter graph consistent with ffprobe, pass -noautorotate before -i in the ffmpeg command.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At helpers/render.py, line 224:

<comment>The `split_stack` crop calculations use `get_source_dims()` (ffprobe coded width/height), but ffmpeg's filter graph auto-rotates frames by default when display-matrix rotation metadata is present (common in phone footage). This means `[0:v]` may see transposed dimensions while the crop math assumes coded dimensions, producing invalid crop coordinates that target the wrong region or exceed the actual frame bounds. For example, a 1920×1080 clip with rotate=90 becomes 1080×1920 in the graph, yet the right-panel crop is computed starting at x=960 with width≈960 — extending past the 1080-wide rotated frame. To keep the filter graph consistent with ffprobe, pass `-noautorotate` before `-i` in the ffmpeg command.</comment>

<file context>
@@ -171,18 +212,65 @@ def extract_segment(
+        pre = f"{tonemap}," if tonemap else ""
+        if layout == "split_stack":
+            half_h = h // 2
+            src_w, src_h = get_source_dims(source)
+            panel_w = src_w / 2
+            aspect = w / half_h  # 1080/960 = 1.125
</file context>
Fix with cubic

Comment thread helpers/render.py
if is_auto:
print(f" grade: {seg_filter or '(none)'}")
extract_segment(src_path, start, duration, seg_filter, out_path, preview=preview, draft=draft)
layout = r.get("layout", "blur_pad")

@cubic-dev-ai cubic-dev-ai Bot Jul 7, 2026

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: New EDL fields layout and split_faces are read from the JSON range objects without validation. A typo in layout (e.g. "split-stack") silently falls back to blur_pad instead of the intended layout, producing a wrong render with no warning. Malformed split_faces values crash the render with an IndexError or TypeError inside _panel_crop. Consider validating layout against the known set of layouts and checking that split_faces is a list of two [float, float] pairs before using it.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At helpers/render.py, line 352:

<comment>New EDL fields `layout` and `split_faces` are read from the JSON range objects without validation. A typo in `layout` (e.g. `"split-stack"`) silently falls back to `blur_pad` instead of the intended layout, producing a wrong render with no warning. Malformed `split_faces` values crash the render with an `IndexError` or `TypeError` inside `_panel_crop`. Consider validating `layout` against the known set of layouts and checking that `split_faces` is a list of two `[float, float]` pairs before using it.</comment>

<file context>
@@ -255,7 +349,8 @@ def extract_all_segments(
         if is_auto:
             print(f"        grade: {seg_filter or '(none)'}")
-        extract_segment(src_path, start, duration, seg_filter, out_path, preview=preview, draft=draft)
+        layout = r.get("layout", "blur_pad")
+        extract_segment(src_path, start, duration, seg_filter, out_path, preview=preview, draft=draft, vertical=vertical, layout=layout, split_faces=r.get("split_faces"))
         seg_paths.append(out_path)
</file context>
Fix with cubic

wigu8989 added 3 commits July 7, 2026 11:35
…rows

Windows terminals default to cp1252, which can't encode U+2192 used in
several progress prints. Reconfigure stdout/stderr to replace
unencodable characters instead of raising UnicodeEncodeError.
Keeps raw downloads/renders moved under the repo (videouse-projects/) out of git tracking.
Excludes .claude/settings.local.json since it can contain
machine-local tokens in permission rules that must never be
committed.

@cubic-dev-ai cubic-dev-ai 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.

2 issues found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".claude/settings.json">

<violation number="1" location=".claude/settings.json:6">
P2: Permission `Bash(npm config get *)` grants wildcard read access to all npm configuration values, which can include `//registry.npmjs.org/:_authToken` and other sensitive auth/settings. No npm usage, package.json, or JavaScript toolchain exists in this project — this widens the attack surface for no functional reason.</violation>

<violation number="2" location=".claude/settings.json:7">
P3: Google Drive MCP tool permissions (`search_files`, `get_file_metadata`) are granted with no code, skill, or documentation reference to Google Drive integration. Remove unused permissions to keep the approval surface clean and avoid prompting users for scope they don't need.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread .claude/settings.json
"allow": [
"Bash(ffprobe *)",
"PowerShell(Get-Process *)",
"Bash(npm config get *)",

@cubic-dev-ai cubic-dev-ai Bot Jul 8, 2026

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: Permission Bash(npm config get *) grants wildcard read access to all npm configuration values, which can include //registry.npmjs.org/:_authToken and other sensitive auth/settings. No npm usage, package.json, or JavaScript toolchain exists in this project — this widens the attack surface for no functional reason.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .claude/settings.json, line 6:

<comment>Permission `Bash(npm config get *)` grants wildcard read access to all npm configuration values, which can include `//registry.npmjs.org/:_authToken` and other sensitive auth/settings. No npm usage, package.json, or JavaScript toolchain exists in this project — this widens the attack surface for no functional reason.</comment>

<file context>
@@ -0,0 +1,11 @@
+    "allow": [
+      "Bash(ffprobe *)",
+      "PowerShell(Get-Process *)",
+      "Bash(npm config get *)",
+      "mcp__claude_ai_Google_Drive__search_files",
+      "mcp__claude_ai_Google_Drive__get_file_metadata"
</file context>
Fix with cubic

Comment thread .claude/settings.json
"Bash(ffprobe *)",
"PowerShell(Get-Process *)",
"Bash(npm config get *)",
"mcp__claude_ai_Google_Drive__search_files",

@cubic-dev-ai cubic-dev-ai Bot Jul 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: Google Drive MCP tool permissions (search_files, get_file_metadata) are granted with no code, skill, or documentation reference to Google Drive integration. Remove unused permissions to keep the approval surface clean and avoid prompting users for scope they don't need.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .claude/settings.json, line 7:

<comment>Google Drive MCP tool permissions (`search_files`, `get_file_metadata`) are granted with no code, skill, or documentation reference to Google Drive integration. Remove unused permissions to keep the approval surface clean and avoid prompting users for scope they don't need.</comment>

<file context>
@@ -0,0 +1,11 @@
+      "Bash(ffprobe *)",
+      "PowerShell(Get-Process *)",
+      "Bash(npm config get *)",
+      "mcp__claude_ai_Google_Drive__search_files",
+      "mcp__claude_ai_Google_Drive__get_file_metadata"
+    ]
</file context>
Fix with cubic

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="checkpoint-summary.md">

<violation number="1" location="checkpoint-summary.md:8">
P2: The Konteks section references absolute Windows paths (`C:\claudeall\BRIEF.md`, `C:\claudeall\checkpoint-summary.md`) that are machine-specific. Since this file is tracked in the repo, these paths will be meaningless to anyone else and won't resolve on macOS/Linux systems. Consider either (a) removing the hardcoded paths and describing the reference context generically, (b) using a relative workspace convention, or (c) keeping such personal paths in a gitignored local file (`.gitignore` already excludes `project.md` for similar session-memory files).</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread checkpoint-summary.md
Belum ada sesi kerja yang terdokumentasi dengan workflow ini.

### Konteks
- Kandidat tool untuk produksi klip campaign Content Rewards — status campaign terkini di `C:\claudeall\BRIEF.md` + `C:\claudeall\checkpoint-summary.md` (level workspace)

@cubic-dev-ai cubic-dev-ai Bot Jul 12, 2026

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: The Konteks section references absolute Windows paths (C:\claudeall\BRIEF.md, C:\claudeall\checkpoint-summary.md) that are machine-specific. Since this file is tracked in the repo, these paths will be meaningless to anyone else and won't resolve on macOS/Linux systems. Consider either (a) removing the hardcoded paths and describing the reference context generically, (b) using a relative workspace convention, or (c) keeping such personal paths in a gitignored local file (.gitignore already excludes project.md for similar session-memory files).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At checkpoint-summary.md, line 8:

<comment>The Konteks section references absolute Windows paths (`C:\claudeall\BRIEF.md`, `C:\claudeall\checkpoint-summary.md`) that are machine-specific. Since this file is tracked in the repo, these paths will be meaningless to anyone else and won't resolve on macOS/Linux systems. Consider either (a) removing the hardcoded paths and describing the reference context generically, (b) using a relative workspace convention, or (c) keeping such personal paths in a gitignored local file (`.gitignore` already excludes `project.md` for similar session-memory files).</comment>

<file context>
@@ -0,0 +1,12 @@
+Belum ada sesi kerja yang terdokumentasi dengan workflow ini.
+
+### Konteks
+- Kandidat tool untuk produksi klip campaign Content Rewards — status campaign terkini di `C:\claudeall\BRIEF.md` + `C:\claudeall\checkpoint-summary.md` (level workspace)
+- Kandidat pemakaian berikutnya: edit sinkron-beat untuk campaign 4D4M "Mad World" (2026-07-12)
+
</file context>
Fix with cubic

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