Repository navigation
Edit Mode and Configure OpenAi Chat Completions - #52
Open
gunsleobezerra wants to merge 25 commits into
Open
gunsleobezerra wants to merge 25 commits into
gunsleobezerra wants to merge 25 commits into
Conversation
gunsleobezerra
commented
Oct 27, 2026
- Edit Mode
- Vídeo Thumbs
- OpenAI Compatible Custom API
- Download Local Whisper Models
Snapshot of the work that was already sitting uncommitted on this branch, split out first so the test commits that follow land on a buildable tree. Backend: - llm: generic OpenAI-compatible provider (URL normalization, JSON-mode payload toggle, SSE chunk parsing, chat-completion text extraction). - media: ffmpeg/ffprobe probing, audio extraction, ASS caption rendering, progress reporting and path helpers. - transcription: local Whisper (Python) + Deepgram normalization, model catalog/download progress, segment building. - lib: caption styles (classic-outline, modern-box, vibrant-*), drawtext filter generation, SRT/ASS export, output slugging. - new modules: hardware (encoder/GPU detection), naming (output naming), progress (pipeline progress events). - db: schema migration for the new project fields. - models: EnvironmentStatus/caption fields. Tooling and docs: - scripts/build-all.mjs plus build:all/linux/windows/android/ios scripts. - release workflow: Android and iOS jobs. - .env.example: OPENAI_BASE_URL / OPENAI_COMPATIBLE_* entries. - pyproject.toml + poetry.lock for the Python (Whisper) side, bun.lock. - .gitignore: ignore artifacts/, VS Code settings, Tauri generated schemas.
Sets up the frontend test harness:
- devDependencies: vitest, jsdom, @testing-library/react,
@testing-library/jest-dom.
- vite.config.ts: `test` block (jsdom environment, globals, setup file,
`src/**/*.{test,spec}.{ts,tsx}` as the test glob, CSS disabled).
- src/test/setup.ts: loads jest-dom matchers and unmounts React trees
after every test so suites cannot leak DOM between cases.
- npm scripts: `test` (single run), `test:watch`, and `test:rust`
(forwards to cargo test in src-tauri).
main.tsx was a single 2.2k-line file that mounted the root, so nothing in it could be imported by a test. Split it into importable pieces: - src/App.tsx: the whole component tree, exported as the default `App`. - src/main.tsx: only creates the React root and renders `<App />`. - src/lib/format.ts: pure helpers `formatModelSize`, `fileName`, `formatTime`, plus new `formatTimeRange` and `formatPercent`. `formatTime` now clamps negative/NaN/Infinity input to 0 instead of rendering `NaN:NaN`. - src/components/common.tsx: `StatusPill`, `PipelineStep` and `EmptyState`. No behavior change for the running app; the duplicated local copies in main.tsx were removed in favor of the imports.
21 tests in three layers: - src/lib/format.test.ts (10): byte-size formatting across B/KB/MB/GB boundaries, file-name extraction for POSIX and Windows paths, mm:ss vs h:mm:ss time output, NaN/Infinity/negative clamping, time ranges that collapse when start and end match, and percent rounding with clamping to 0..100. - src/components/common.test.tsx (7): StatusPill label and tone mapping for every project status, PipelineStep active/done/pending styling, and EmptyState title/description/action rendering. - src/App.integration.test.tsx (4): mounts the real `App` with `invoke`, `listen` and the dialog plugin mocked. Verifies the onboarding gate appears when the environment is not ready, the sidebar renders the project list, the empty state shows when there are no projects, and clicking a row loads its detail and transcript segment count.
`db`, `llm`, `media`, `progress` and `transcription` were private, so an integration test under `src-tauri/tests/` could not reach them through `autoshorts_lib`. Promote all of them to `pub mod`, matching `hardware` and `naming` which were already public. This only widens the library's API surface; the Tauri binary and its commands are unaffected.
10 unit tests for `media`: - progress parsing: microsecond values (`out_time_us`), `HH:MM:SS.mmm` clock values, and unknown/invalid keys being ignored instead of aborting the parse. - `parse_clock`: seconds-only, minute, hour forms and malformed input. - `ass_filter_arg`: escaping of `\ : ' ,` for the `subtitles` filter, falling back to the bare file name when the path has no parent, and `None` when there is no file name at all. - `absolute_path`: leaves absolute paths alone, resolves relative ones against the current directory. - `command_exists`: false for a binary that cannot exist.
12 unit tests for `transcription`: - download progress: percentage parsing out of the model downloader output, plus lines without a percentage being ignored. - Whisper stdout parsing: `[00:00:01.500 --> 00:00:03.000]` timestamps and the segment-end helper. - `build_segments`: empty input yields no segments, consecutive words are joined until a break, and a sentence-ending word closes the segment. - Deepgram: normalization of the alternative/words payload, and errors for a response with no alternative or no words. - Whisper raw JSON: normalization, and an error when `segments` is absent. - the bundled model catalog is non-empty and every entry has the fields the UI needs.
17 unit tests for `llm`: - `normalize_chat_completions_url`: base URLs, `/v1` bases, URLs that already end in `/chat/completions`, and trailing slashes. - `compact_segments`: one numbered line per segment. - `parse_candidate_json` robustness against real model output: fenced ```json blocks, a root array, a single bare candidate object, alternative key names for start/end/score, clips shorter than the minimum being dropped, clips without a hook being dropped, loose string scores, clamping out-of-range scores, truncation to 10 candidates, and a hard error on invalid JSON. - SSE: chunked `data:` lines are concatenated, non-chunk payloads and empty streams are rejected. - `extract_completion_text`: all chat-completion content shapes, and `None` when there is no content. - `body_snippet`: long bodies get truncated. - `chat_completion_payload`: JSON mode toggles `response_format`.
14 unit tests for the helpers that live in `lib.rs`:
- `generate_srt`: three-word chunking, text concatenation, index numbers,
clipping to the requested window, and an empty result outside it.
(The window in the clipping test is 0.0..4.0 because the filter is
`w.start < end_sec`, exclusive.)
- `format_srt_time` / `format_ass_time`: zero, sub-second rounding,
minute and hour rollover, and the ASS centisecond field.
- `build_ass_captions`: header (Script Info / V4+ Styles / Events),
one Dialogue line per word, and escaping of `{ } \` in the text.
- `project_output_slug`: keeps letters and digits, collapses separators,
strips leading/trailing dashes, and never returns an empty slug.
- `validate_media_extension`: accepts the supported video/audio
extensions case-insensitively and rejects the rest.
- `demo_transcript`: has words, segments and a matching duration.
`src-tauri/tests/db_integration.rs` drives `autoshorts_lib::db::Database` against a real on-disk SQLite file instead of mocking it, so schema migration, foreign keys and cascades are exercised for real. 12 tests: - projects: create/read, detail starts empty and tracks the transcript, rename + status updates persist, delete cascades to candidates, clips and transcripts. - transcripts: saving a second transcript replaces the first. - candidates: `replace_candidates` ranks rows 1..n and auto-selects the top six, is idempotent when called twice, and `get_candidate_with_project` joins both tables. - clips: selection toggling by rank, and `clip updates` keeping the existing render paths when `None` is passed. - recovery: reopening the database resets clips stuck in `cutting`, and opening the same file twice reuses the existing schema. The test file carries a small `TempDir` helper (env::temp_dir + an `AtomicU64` suffix, cleaned up on `Drop`) so no extra dev-dependency is needed.
New `test` job on ubuntu-22.04 that runs before anything is published: 1. checkout, Node 20, stable Rust toolchain, `Swatinem/rust-cache` scoped to `src-tauri`. 2. Linux system dependencies (webkit2gtk, gtk, libappindicator, ...) needed to compile the Tauri crate. 3. `npm ci`, `npm run build` (the Rust build embeds `dist/`, so it has to exist first), `npm test`. 4. `cargo test --all-targets` for the unit and integration suites. `release`, `android` and `ios` now declare `needs: test`, so a red test suite stops the whole matrix instead of shipping broken binaries. Also fixes the `matrix` indentation under `release`.
Adds "4. Run the Tests" to the README with the commands and a table of every test file: - `npm test` / `npm run test:watch` for Vitest, - `npm run test:rust` (or `cargo test`) for the Rust suites, - the three frontend files and the five Rust files with what each covers. Renumbers "Multi-Platform Build" to 5.
`naming::unique_path` appended `-2`, `-3`, … whenever the target file already existed, so re-cutting a clip after editing its hook left the old render behind and the project folder grew one duplicate per attempt. Clip names are already deterministic (project slug + rank + hook + timestamps), so the render path is now `clips_dir.join(file_name)`: a re-cut overwrites the previous render instead of accumulating copies. Removes `unique_path` and its two tests from `naming`.
Configure OpenAI pattern
bun.lock was committed, and tauri-action chooses the package manager from lockfiles (usesBun before usesNpm), so Windows runners without bun failed. Remove the lockfile, ignore it, pin packageManager to npm, assert it in CI, pass tauriScript explicitly, and only cut releases on v* tags so branch pushes no longer create a bogus 'main' release.
- scripts/build-all.mjs: remove alvos android/ios e helpers (androidSdk, ANDROID_RUST_TARGETS, installedRustTargets); adiciona alvo macos (dmg/app) - package.json: build:android/build:ios -> build:macos - README: matriz de plataformas e comandos atualizados
…dinâmico Motor novo em `autoedit.rs`: - `detect_silences` roda `ffmpeg silencedetect` na janela do clipe; - `build_plan`/`plan_from_silences` transformam as pausas em lista de cortes, subtraindo da detecção tudo que o transcript diz ser fala (evita cortar voz baixa), aplicando padding nas bordas e alternando zoom punch-in nos trechos mantidos; - `remap_cues` reescreve as legendas na linha do tempo comprimida, removendo as que caíram em pausa cortada e dividindo as que atravessam um corte. Render (`media.rs`): - `ClipRenderRequest` ganhou `has_audio` e `segments`; - com cut list o ffmpeg usa `-filter_complex` (trim/atrim + setpts/atempo por segmento, `concat`, crop/scale e `ass` uma única vez no resultado final) em vez de `-vf`; - `-t` passa a cobrir a janela de origem (não a duração de saída), senão os últimos segmentos eram truncados; - punch-in é aplicado por segmento, antes do concat, porque depois não haveria mais como distinguir os trechos. Persistência: `clip_edits.auto_edit_json` + `AutoEditSettings::sanitized`. UI: painel "Auto-edit: cortar silêncios" no editor do clipe (toggle, limite de silêncio, pausa mínima, respiro, modo cortar/acelerar, velocidade e zoom dinâmico) com resumo em texto e persistência junto do resto do `ClipEdit`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.