Make loadLocalSourceFile and loadRemoteSourceFile static so they can be
called without an instance. loadSourceFile applies withTimeout around
each static call. loadFileAsArrayBuffer delegates to the same static
methods and extracts ArrayBuffer + contentType from the blob, eliminating
the duplicated IPC/fetch branching logic.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Restore loadSourceFile as a thin router (local vs remote) and extract
the IPC and fetch paths into dedicated private methods, each containing
the original logic from main.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Change return type to { data, contentType } so the fetched Content-Type
header is available to callers. loadSourceFile uses it to set the Blob
MIME type for https:/blob: URLs instead of always falling back to
application/octet-stream. useAudioPeaks destructures only { data }.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- computePeaksInWorker now accepts an AbortSignal; terminates the worker
immediately on abort and rejects with AbortError so orphaned workers
cannot outlive the effect cleanup
- useAudioPeaks wires an AbortController into the effect; controller.abort()
fires alongside the existing cancelled flag on URL change or unmount
- loadSourceFile handles data: URLs by parsing the MIME type, deriving a
safe filename (e.g. video.mp4), and setting Blob type correctly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add docstrings to all undocumented functions and methods across the
files touched in this branch: getAudioCtx, Row component, and all
StreamingVideoDecoder methods (loadSourceFile, computeSegments,
getExportMetrics, splitBySpeed, getDemuxer, cancel, destroy, withTimeout).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move the peaks null-check after clearRect so a previously drawn
waveform is erased when peaks transitions to null (e.g. on URL change
or decode failure) rather than lingering on screen.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use 剪輯 (editing/clip) instead of 修剪 (trimming) to match the term
already used in the trim section throughout zh-TW strings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reset peaks to null immediately when an uncached URL is set, so the
previous video's waveform is not shown during decode. Also clear on
decode failure so stale data does not persist indefinitely.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rename to BackgroundWaveform to reflect its visual role rather than
structural placement. Remove the redundant wrapper div — Row already
provides relative overflow-hidden, so the canvas can sit absolute
inset-0 directly and observe itself via ResizeObserver.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add timeline.title and timeline.waveform keys to every settings.json
locale file. Replace all hardcoded "Timeline" and "Show Audio Waveform
on Trim Track" strings in SettingsPanel with t() calls.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move computePeaks into audioPeaksWorker.ts — runs off the main thread
with zero-copy channel buffer transfer
- Replace module-level peaksCache Map with a useRef scoped to the hook
instance — no global mutable state, toggle off/on still instant
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add a single exported loadFileAsArrayBuffer in streamingDecoder.ts that
owns the IPC-vs-fetch branching for local and remote video URLs.
StreamingVideoDecoder.loadSourceFile and useAudioPeaks both delegate to
it, removing the duplicated readBinaryFile/fetch logic.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move fetch/decode/cache logic out of RowWaveform into a standalone
useAudioPeaks hook. RowWaveform is now a pure canvas renderer that
accepts pre-computed peaks as a prop. TimelineEditor calls the hook
and passes peaks down, skipping decoding entirely when waveform is off.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The 0.25 bump was a workaround for hint visibility over the waveform
background, but is now stale — waveform defaults to off and hints only
appear on empty rows anyway. Restores consistency with all other row hints.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace AudioWaveform icon with Brackets on the Timeline panel tab and section header
- Rename toggle label from "Waveform" to "Show Audio Waveform on Trim Track"
- Make toggle full-width to accommodate the longer label
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add "Timeline" as a dedicated SettingsPanelMode with AudioWaveform icon
- Waveform toggle now lives exclusively in the Timeline panel (not in every panel)
- Default showTrimWaveform to false so trim row starts with visible hint text
- Guard AccordionItem render with activePanelMode === "timeline" to prevent bleed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add RowWaveform component (refactored from TrimWaveform) that decodes
audio via AudioContext, caches peaks per URL, and renders a faint
waveform canvas behind any timeline row using useTimelineContext() for
zoom/pan alignment
- Wire RowWaveform as background of the trim row in TimelineEditor
- Add showTrimWaveform boolean to EditorState / ProjectEditorState with
default true; persists across saves/loads
- Add Timeline Settings accordion section in SettingsPanel (always
visible) with a Waveform toggle to enable/disable the visualization
- Bump hint text opacity from 0.12 to 0.25 so "Press T to add trim"
remains readable over the waveform background
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
PR #600 (now on main) removed WEBCAM_TARGET_WIDTH/HEIGHT and switched
this call site to width/height: 0 so the native helper picks the
camera's native dimensions. Align this branch with that so CI's
fresh PR-merge stops erroring on the undeclared identifiers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes MAX_PLAYBACK_SPEED and DEFAULT_WEBCAM_SIZE_PRESET (TS6133) and
runs biome's organize-imports to satisfy the Lint check.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Record browser webcam sidecar when native Windows capture is active.
Add native webcam sidecar output and DirectShow NV12/YUY2 fallback.
Sample exported webcam frames by source timestamp.