Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
name: Bug report
about: Report a problem
labels: bug
---

## Environment

- OS:
- Python version:
- Browser:

## Steps to reproduce

1.
2.
3.

## Expected behavior

## Actual behavior

## Logs / screenshots

17 changes: 17 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an improvement
labels: enhancement
---

## Problem

Describe the problem or limitation you're experiencing.

## Proposed solution

Describe what you'd like to happen.

## Alternatives considered

Any other approaches you've thought about.
17 changes: 17 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## What

Brief description of the change.

## Why

Motivation or issue link.

## How

Implementation approach.

## Testing

- [ ] `poetry run pytest -v` passes
- [ ] Manually tested in browser
- [ ] Tested in demo mode (`?demo`)
33 changes: 33 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-in-project: true

- name: Install dependencies
run: poetry install --no-interaction

- name: Run tests
run: poetry run pytest -v
15 changes: 15 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

## Environment
- Requires `TM_OPENAI_API_KEY` env var or `.env` file (not needed for demo mode)
- `TM_SUMMARIZE_MODEL` env var (default: `gpt-4o`) — model used for AI summarization
- Tests set a dummy key in `conftest.py` — no real key needed for unit tests

## Demo Mode
Expand All @@ -20,6 +21,7 @@
## Architecture
- FastAPI app with SSE-based transcription pipeline: download → chunk → whisper API → save
- History stored as markdown files with YAML frontmatter in `results/` — no database
- AI summarization via OpenAI Chat API — summaries stored as sidecar files `results/{record_id}_summary.md`
- Frontend is vanilla HTML/CSS/JS in `app/static/` — no build step

## Key Patterns
Expand All @@ -29,6 +31,9 @@
- `complete_record()` / `fail_record()` rebuild the full YAML meta dict from parsed record — always include all fields
- `_write_md()` uses `sort_keys=False` to preserve frontmatter key order
- Audio cached in `results/{record_id}.mp3` after download — reused by retranscribe, deleted with record
- Summary sidecar: `results/{record_id}_summary.md` with YAML frontmatter (prompt, created_at) + body
- `delete_record()` cascades to delete summary sidecar + audio cache
- Video title prepended as first line of transcript and summary body in `api.py` (all codepaths: transcribe, demo, retranscribe, summarize, demo summarize)

## Two Whisper Models
- `gpt-4o-transcribe` (default) — plain text output
Expand All @@ -49,6 +54,16 @@
- Mock external deps (yt-dlp, ffmpeg, OpenAI) in unit tests
- Integration tests marked with `@pytest.mark.integration`

## Summarize Feature
- Summarize button appears on completed transcript cards (expands card if collapsed)
- User can enter a custom prompt or use the default
- Summary stored as `results/{record_id}_summary.md` with YAML frontmatter (prompt, created_at)
- Video title prepended as first line of both transcript body and summary body
- Expanded cards show Transcript/Summary tab toggle when a summary exists
- Copy button copies based on active tab (transcript or summary), toast says "Transcript copied" / "Summary copied"
- Demo mode: simulated 2s delay, canned summary text
- Endpoints: `POST /api/history/{id}/summarize`, `GET /api/history/{id}/summary`

## Gotchas
- `_parse_md()` coerces all YAML values to strings (line 57) except duration (explicitly int)
- Old records may lack newer frontmatter fields — always use `.get("field", "")` with defaults
Expand Down
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 dmitry-kostin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading