mediasense 0.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. mediasense-0.4.1/.gitattributes +8 -0
  2. mediasense-0.4.1/.github/workflows/ci.yml +34 -0
  3. mediasense-0.4.1/.github/workflows/release.yml +58 -0
  4. mediasense-0.4.1/.gitignore +14 -0
  5. mediasense-0.4.1/LICENSE +21 -0
  6. mediasense-0.4.1/PKG-INFO +263 -0
  7. mediasense-0.4.1/README.md +219 -0
  8. mediasense-0.4.1/README.pt-BR.md +137 -0
  9. mediasense-0.4.1/docs/demo.gif +0 -0
  10. mediasense-0.4.1/docs/make_demo.py +165 -0
  11. mediasense-0.4.1/install.ps1 +123 -0
  12. mediasense-0.4.1/install.sh +67 -0
  13. mediasense-0.4.1/mcpb/.mcpbignore +5 -0
  14. mediasense-0.4.1/mcpb/icon.png +0 -0
  15. mediasense-0.4.1/mcpb/make_icon.py +47 -0
  16. mediasense-0.4.1/mcpb/manifest.json +69 -0
  17. mediasense-0.4.1/mcpb/pyproject.toml +6 -0
  18. mediasense-0.4.1/mcpb/src/server.py +6 -0
  19. mediasense-0.4.1/pyproject.toml +61 -0
  20. mediasense-0.4.1/skill/mediasense/SKILL.md +84 -0
  21. mediasense-0.4.1/src/mediasense/__init__.py +5 -0
  22. mediasense-0.4.1/src/mediasense/__main__.py +5 -0
  23. mediasense-0.4.1/src/mediasense/api.py +278 -0
  24. mediasense-0.4.1/src/mediasense/cli.py +372 -0
  25. mediasense-0.4.1/src/mediasense/edit.py +411 -0
  26. mediasense-0.4.1/src/mediasense/export.py +270 -0
  27. mediasense-0.4.1/src/mediasense/fetch.py +204 -0
  28. mediasense-0.4.1/src/mediasense/jobs.py +124 -0
  29. mediasense-0.4.1/src/mediasense/mcp_server.py +480 -0
  30. mediasense-0.4.1/src/mediasense/media.py +338 -0
  31. mediasense-0.4.1/src/mediasense/models.py +239 -0
  32. mediasense-0.4.1/src/mediasense/setup.py +264 -0
  33. mediasense-0.4.1/src/mediasense/skill.py +55 -0
  34. mediasense-0.4.1/src/mediasense/transcribe.py +514 -0
  35. mediasense-0.4.1/src/mediasense/video.py +159 -0
  36. mediasense-0.4.1/tests/conftest.py +89 -0
  37. mediasense-0.4.1/tests/test_backends.py +239 -0
  38. mediasense-0.4.1/tests/test_interfaces.py +118 -0
  39. mediasense-0.4.1/tests/test_jobs.py +72 -0
  40. mediasense-0.4.1/tests/test_media.py +181 -0
  41. mediasense-0.4.1/tests/test_setup.py +117 -0
  42. mediasense-0.4.1/tests/test_skill.py +54 -0
  43. mediasense-0.4.1/tests/test_text.py +155 -0
  44. mediasense-0.4.1/tests/test_understand.py +202 -0
@@ -0,0 +1,8 @@
1
+ # Normalise line endings in the repository; binaries are never touched.
2
+ * text=auto eol=lf
3
+ *.ps1 text eol=crlf
4
+ *.gif binary
5
+ *.png binary
6
+ *.jpg binary
7
+ *.mp4 binary
8
+ *.zip binary
@@ -0,0 +1,34 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ${{ matrix.os }}
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest, windows-latest]
15
+ python: ["3.10", "3.13"]
16
+ steps:
17
+ - uses: actions/checkout@v5
18
+ - uses: actions/setup-python@v6
19
+ with:
20
+ python-version: ${{ matrix.python }}
21
+
22
+ - name: Install FFmpeg (Linux)
23
+ if: runner.os == 'Linux'
24
+ run: sudo apt-get update && sudo apt-get install -y ffmpeg
25
+ - name: Install FFmpeg (macOS)
26
+ if: runner.os == 'macOS'
27
+ run: brew install ffmpeg
28
+ - name: Install FFmpeg (Windows)
29
+ if: runner.os == 'Windows'
30
+ run: choco install ffmpeg -y --no-progress
31
+
32
+ - run: pip install -e ".[dev,mcp]"
33
+ - run: ruff check src tests
34
+ - run: pytest -q
@@ -0,0 +1,58 @@
1
+ name: Release
2
+
3
+ # Push a tag like v0.4.1 to publish:
4
+ # - the Python package on PyPI (trusted publishing, see README "Releasing")
5
+ # - a GitHub release with the wheel, the Claude skill zip and the Claude Desktop extension (.mcpb)
6
+ on:
7
+ push:
8
+ tags: ["v*"]
9
+
10
+ jobs:
11
+ release:
12
+ runs-on: ubuntu-latest
13
+ permissions:
14
+ contents: write # create the GitHub release
15
+ id-token: write # PyPI trusted publishing
16
+ steps:
17
+ - uses: actions/checkout@v5
18
+ - uses: actions/setup-python@v6
19
+ with:
20
+ python-version: "3.12"
21
+ - uses: actions/setup-node@v5
22
+ with:
23
+ node-version: "22"
24
+
25
+ - name: Check the tag matches the package version
26
+ run: |
27
+ V=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
28
+ test "v$V" = "$GITHUB_REF_NAME" || { echo "tag $GITHUB_REF_NAME != version $V in pyproject.toml"; exit 1; }
29
+ echo "VERSION=$V" >> "$GITHUB_ENV"
30
+
31
+ - name: Build the Python package
32
+ run: pip install build && python -m build
33
+
34
+ - name: Skill zip (upload in Claude → Settings → Skills)
35
+ run: |
36
+ mkdir -p out/skill
37
+ cp -r skill/mediasense out/skill/
38
+ (cd out/skill && zip -r ../mediasense-skill.zip mediasense)
39
+
40
+ - name: Claude Desktop extension (.mcpb)
41
+ run: |
42
+ cp -r mcpb out/ext
43
+ sed -i "s/\"version\": \"0.0.0\"/\"version\": \"$VERSION\"/" out/ext/manifest.json
44
+ sed -i "s/0\.0\.0/$VERSION/g" out/ext/pyproject.toml
45
+ npx -y @anthropic-ai/mcpb validate out/ext/manifest.json
46
+ npx -y @anthropic-ai/mcpb pack out/ext out/mediasense.mcpb
47
+
48
+ - name: Publish to PyPI
49
+ # needs the one-time trusted-publisher setup on pypi.org; the GitHub release is made either way
50
+ continue-on-error: true
51
+ uses: pypa/gh-action-pypi-publish@release/v1
52
+
53
+ - name: Create GitHub release
54
+ env:
55
+ GH_TOKEN: ${{ github.token }}
56
+ run: |
57
+ gh release create "$GITHUB_REF_NAME" dist/*.whl dist/*.tar.gz out/mediasense-skill.zip out/mediasense.mcpb \
58
+ --title "mediasense $GITHUB_REF_NAME" --generate-notes
@@ -0,0 +1,14 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .venv/
5
+ venv/
6
+ dist/
7
+ build/
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ # media and outputs
11
+ *.transcript.json
12
+ *.storyboard/
13
+ *.edited.*
14
+ *.placed.*
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mediasense contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,263 @@
1
+ Metadata-Version: 2.5
2
+ Name: mediasense
3
+ Version: 0.4.1
4
+ Summary: Give Claude ears and eyes: understand, summarize and edit audio/video files or links (TikTok, YouTube…) with word-level timestamps. MCP server + CLI, runs locally.
5
+ Project-URL: Homepage, https://github.com/joaoestella/mediasense
6
+ Project-URL: Issues, https://github.com/joaoestella/mediasense/issues
7
+ License: MIT
8
+ License-File: LICENSE
9
+ Keywords: claude,ffmpeg,mcp,subtitles,transcription,video editing,whisper,word timestamps
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
14
+ Classifier: Topic :: Multimedia :: Video :: Non-Linear Editor
15
+ Requires-Python: >=3.10
16
+ Requires-Dist: pillow>=9.0
17
+ Provides-Extra: all
18
+ Requires-Dist: faster-whisper>=1.0; extra == 'all'
19
+ Requires-Dist: mcp>=1.2; extra == 'all'
20
+ Requires-Dist: numpy; extra == 'all'
21
+ Requires-Dist: yt-dlp[curl-cffi,default]>=2024.1; extra == 'all'
22
+ Provides-Extra: api
23
+ Requires-Dist: openai>=1.30; extra == 'api'
24
+ Provides-Extra: dev
25
+ Requires-Dist: numpy; extra == 'dev'
26
+ Requires-Dist: pytest>=7; extra == 'dev'
27
+ Requires-Dist: ruff; extra == 'dev'
28
+ Provides-Extra: ffmpeg
29
+ Requires-Dist: static-ffmpeg>=2.5; extra == 'ffmpeg'
30
+ Provides-Extra: gpu
31
+ Requires-Dist: nvidia-cublas-cu12; extra == 'gpu'
32
+ Requires-Dist: nvidia-cuda-runtime-cu12; extra == 'gpu'
33
+ Requires-Dist: nvidia-cudnn-cu12<10,>=9; extra == 'gpu'
34
+ Provides-Extra: mcp
35
+ Requires-Dist: mcp>=1.2; extra == 'mcp'
36
+ Provides-Extra: url
37
+ Requires-Dist: yt-dlp[curl-cffi,default]>=2024.1; extra == 'url'
38
+ Provides-Extra: whisper
39
+ Requires-Dist: faster-whisper>=1.0; extra == 'whisper'
40
+ Requires-Dist: numpy; extra == 'whisper'
41
+ Provides-Extra: whisperx
42
+ Requires-Dist: whisperx>=3.1; extra == 'whisperx'
43
+ Description-Content-Type: text/markdown
44
+
45
+ # mediasense
46
+
47
+ **Give Claude ears and eyes.** Paste a TikTok, YouTube or Instagram link (or point at a file) in Claude
48
+ Code or Claude Desktop and ask in plain language. Claude can then summarize the video, explain what
49
+ happens in it, find the moment something is said, or edit it.
50
+
51
+ ```text
52
+ you: summarize this https://www.tiktok.com/@someone/video/7350…
53
+ you: what does he show at 0:30? and what tool is he talking about?
54
+ you: clean up ~/Desktop/podcast.m4a — remove the "um"s and long pauses
55
+ you: make short captions for ~/Videos/reel.mp4
56
+ you: put intro.mp3 under the first 5 seconds of talk.mp4, ducked
57
+ ```
58
+
59
+ ![mediasense in Claude: a TikTok link is downloaded, transcribed and summarized with timestamps](docs/demo.gif)
60
+
61
+ <sub>Real output for a 17-second TikTok by @elim.doc, shown with the creator's permission. Regenerate the
62
+ animation with `python docs/make_demo.py`.</sub>
63
+
64
+ mediasense runs **on your computer**: it downloads the link, transcribes speech in ~99 languages with a
65
+ timestamp for every word, picks key frames at scene changes, and hands Claude a transcript, a shot list
66
+ and contact-sheet images. Nothing is uploaded anywhere.
67
+
68
+ [Português 🇧🇷](README.pt-BR.md)
69
+
70
+ ## Setup
71
+
72
+ **Windows** – paste in PowerShell:
73
+
74
+ ```powershell
75
+ irm https://raw.githubusercontent.com/joaoestella/mediasense/main/install.ps1 | iex
76
+ ```
77
+
78
+ **macOS / Linux** – paste in a terminal:
79
+
80
+ ```bash
81
+ curl -LsSf https://raw.githubusercontent.com/joaoestella/mediasense/main/install.sh | sh
82
+ ```
83
+
84
+ Then **quit Claude Desktop completely** (tray/menu-bar icon → Quit), open it again and ask
85
+ *"summarize this video: <link>"*. The first transcription downloads the speech model (≈ 500 MB).
86
+
87
+ <details>
88
+ <summary>Prefer to read the script before running it?</summary>
89
+
90
+ ```powershell
91
+ irm https://raw.githubusercontent.com/joaoestella/mediasense/main/install.ps1 -OutFile install.ps1
92
+ notepad install.ps1
93
+ powershell -ExecutionPolicy Bypass -File .\install.ps1
94
+ ```
95
+
96
+ (macOS/Linux: `curl -LsSfO …/install.sh`, read it, then `sh install.sh`.)
97
+
98
+ The installer only installs what is missing — Python 3.12 and FFmpeg via `winget` (Homebrew/apt on
99
+ macOS/Linux) and `pipx` via pip — then `pipx install`s mediasense from this repository and runs
100
+ `mediasense setup`. It stops at the first failed step.
101
+ </details>
102
+
103
+ <details>
104
+ <summary>Manual setup (no script)</summary>
105
+
106
+ ```powershell
107
+ winget install ffmpeg # macOS: brew install ffmpeg · Linux: sudo apt install ffmpeg
108
+ python -m pip install --user pipx
109
+ python -m pipx ensurepath # then close and reopen the terminal
110
+ python -m pipx install "mediasense[all]"
111
+ mediasense setup -n # preview what setup will change
112
+ mediasense setup
113
+ mediasense doctor
114
+ ```
115
+
116
+ Use `python -m pipx …` rather than plain `pipx` right after installing it: the `pipx` command only
117
+ appears on PATH in a new terminal. No Git needed.
118
+ </details>
119
+
120
+ <details>
121
+ <summary>One-click Claude Desktop extension (experimental)</summary>
122
+
123
+ Download **[mediasense.mcpb](https://github.com/joaoestella/mediasense/releases/latest/download/mediasense.mcpb)**
124
+ and double-click it (or drag it into Claude Desktop → Settings → Extensions). No Python, pipx or
125
+ FFmpeg needed: Claude Desktop sets up Python by itself, and FFmpeg is downloaded on first use. The
126
+ first start takes a few minutes while it installs everything. This uses Claude Desktop's new "UV"
127
+ extension type, so if it doesn't work on your version, use the installer above.
128
+ </details>
129
+
130
+ ### What `mediasense setup` changes
131
+
132
+ - **Claude Desktop:** adds one entry, `mcpServers.mediasense`, to `claude_desktop_config.json`
133
+ (`%APPDATA%\Claude\` – or `%LOCALAPPDATA%\Claude-Data\claude_…\` for the Microsoft Store app –
134
+ `~/Library/Application Support/Claude/` on macOS, `~/.config/Claude/` on Linux; Claude Desktop →
135
+ Settings → Developer → Edit Config opens the one your app uses). Everything else in the file is kept, and the previous file is saved next to it as
136
+ `claude_desktop_config.json.<date>.bak`. If the file isn't valid JSON, setup stops without touching it.
137
+ - **Claude Code** (if installed): runs `claude mcp add --scope user mediasense -- <path>\mediasense mcp`.
138
+ - Nothing else. `mediasense setup -n` shows the exact changes without making them; `--desktop` or
139
+ `--code` limits it to one app. To undo: remove the `mediasense` entry from the config file and run
140
+ `claude mcp remove mediasense --scope user`.
141
+
142
+ Updating on Windows and pipx says a file "is being used by another process"? Claude Desktop is still
143
+ running the old server: `Get-Process mediasense | Stop-Process -Force`, then install again (the
144
+ installer script does this for you).
145
+
146
+ Something not working? `mediasense doctor` checks FFmpeg, the speech model, the GPU, link downloads and
147
+ the Claude connection.
148
+
149
+ ### Teach Claude when to use it (recommended)
150
+
151
+ mediasense comes with a **skill**: a short guide that makes Claude reach for mediasense whenever you
152
+ paste a video link, instead of trying to open the page (TikTok & co. block that).
153
+
154
+ - **Claude Code:** installed automatically by `mediasense setup`.
155
+ - **Claude Desktop / claude.ai:** download
156
+ [mediasense-skill.zip](https://github.com/joaoestella/mediasense/releases/latest/download/mediasense-skill.zip)
157
+ (the installer also saves it to `Downloads/mediasense/`), then in Claude open **Settings → Skills** and
158
+ upload it. One time only; it syncs to all your devices.
159
+
160
+ > **Note:** Claude Desktop sends files you attach in the chat to the model, not to your computer, so give
161
+ > mediasense a **link or a file path** instead (in Claude Code you can drag the file into the terminal).
162
+
163
+ ### Slash commands
164
+
165
+ The server adds ready-made prompts. In Claude Code they appear as `/mcp__mediasense__summarize` and so on.
166
+
167
+ | Prompt | Does |
168
+ |---|---|
169
+ | `summarize` | gist, key points with timestamps, steps, names and links, call to action |
170
+ | `explain_video` | shot-by-shot explanation, plus how the video is built (hook, structure) |
171
+ | `clean_up` | remove fillers and long pauses, show the plan first, render after your OK |
172
+ | `subtitles` | SRT captions, standard or short 1–3-word style for vertical video |
173
+
174
+ ### Tools Claude gets
175
+
176
+ | Tool | What it does |
177
+ |---|---|
178
+ | `understand_media` | **one call**: download link, transcribe, key frames + speech per shot, post title/description |
179
+ | `transcribe` | speech → `<file>.transcript.json` with word timestamps; `vocabulary` fixes brand names |
180
+ | `read_transcript`, `search_transcript` | read a time range or find every time a phrase is said |
181
+ | `plan_edit`, `render_edit` | cut phrases, passages, fillers, silences or ranges; preview, then render |
182
+ | `export_transcript` | SRT, VTT, TXT, CSV, JSON |
183
+ | `place_audio` | insert a clip at a timestamp (mix / duck / replace) |
184
+ | `watch_video`, `get_frame` | contact sheets, or one frame at a given time |
185
+ | `media_info` | duration, resolution, fps, streams |
186
+ | `check_job` | result of long work: new videos and the first run reply "still working" and finish in the background |
187
+
188
+ Long work never hits Claude's tool time limit: if a video takes more than ~30 s (a long video on a
189
+ CPU, or the very first run while the speech model downloads), the tool answers "still working" with a
190
+ progress percentage and Claude checks back with `check_job` until it's done.
191
+
192
+ All tools accept a file path **or a link**. Links are downloaded once to `~/Downloads/mediasense`
193
+ (change with `MEDIASENSE_HOME`) and reused.
194
+
195
+ ## Command line
196
+
197
+ Everything also works without Claude:
198
+
199
+ ```bash
200
+ mediasense understand "https://youtu.be/…" # transcript + shots + metadata, as text
201
+ mediasense transcribe talk.mp4 -l pt --vocab "Cloudflare, Claude" --also srt
202
+ mediasense search talk.transcript.json "next quarter"
203
+ mediasense edit talk.mp4 --fillers --silences 0.7 -n # -n = only show the plan
204
+ mediasense edit talk.mp4 --fillers --silences 0.7 --srt --edl --fcpxml
205
+ mediasense edit talk.mp4 --cut-between "let me check" "okay so" --cut-range 12:03-12:40
206
+ mediasense export talk.transcript.json captions.srt --words-per-cue 2
207
+ mediasense place video.mp4 voiceover.wav --at 0:12.5 --mode duck
208
+ mediasense storyboard reel.mp4
209
+ mediasense fetch "https://www.tiktok.com/@…/video/…"
210
+ ```
211
+
212
+ Edits never touch the original: results are written as `<name>.edited.*` / `<name>.placed.*`.
213
+ EDL opens in Premiere, Resolve and Avid; FCPXML in Final Cut Pro and Resolve.
214
+
215
+ ## Good to know
216
+
217
+ - **Names and jargon.** Whisper may write "Cloud Fair" for Cloudflare. Pass `--vocab` (Claude does this
218
+ automatically when it can infer the names from the title or the screen).
219
+ - **Fillers.** Whisper tends to leave hesitations out; transcribe with `--verbatim` when you want to cut
220
+ them. Real words are protected per language ("um" is an article in Portuguese, so it is never cut
221
+ there). Ambiguous words like "like", "tipo" or "né" are only removed if you list them.
222
+ - **Speed.** Everything works on a plain CPU: short clips take seconds, a few minutes of audio takes
223
+ about as long as the audio with the default `small` model (`base` is faster, `medium` more accurate).
224
+ No GPU? `--backend openai` sends the audio to an OpenAI-compatible transcription API instead
225
+ (fast on any machine, but the audio leaves your computer).
226
+ - **NVIDIA GPU (optional, much faster).** mediasense uses it automatically once the CUDA libraries are
227
+ present; no CUDA toolkit needed:
228
+
229
+ ```bash
230
+ python -m pipx inject mediasense nvidia-cublas-cu12 "nvidia-cudnn-cu12>=9,<10" nvidia-cuda-runtime-cu12
231
+ ```
232
+
233
+ (≈ 1.5 GB; needs a driver that supports CUDA 12 – `mediasense doctor` checks both). Restart Claude
234
+ Desktop afterwards.
235
+ - **Word timing** is approximate (0.1–0.2 s). For tighter cuts and speaker labels use
236
+ `--backend whisperx` (`pip install "mediasense[whisperx]"`).
237
+ - Downloading from links follows each site's terms. Use it for content you're allowed to download.
238
+
239
+ ## Development
240
+
241
+ ```bash
242
+ git clone https://github.com/joaoestella/mediasense && cd mediasense
243
+ pip install -e ".[dev,mcp]"
244
+ pytest
245
+ ```
246
+
247
+ The tests build synthetic audio/video with FFmpeg and use fake model and downloader libraries, so they
248
+ run in seconds with nothing to download. Ideas welcome: more filler words for your language, a
249
+ one-click Claude Desktop extension (`.mcpb`), and a GUI.
250
+
251
+ ## Releasing
252
+
253
+ 1. Bump `version` in `pyproject.toml` and `src/mediasense/__init__.py`, commit.
254
+ 2. `git tag vX.Y.Z && git push origin vX.Y.Z`. The Release workflow publishes to PyPI and creates a
255
+ GitHub release with the wheel, `mediasense-skill.zip` and `mediasense.mcpb`.
256
+
257
+ One-time PyPI setup (trusted publishing, no token): on pypi.org → *Your account → Publishing → Add a
258
+ new pending publisher*: project `mediasense`, owner `joaoestella`, repository `mediasense`, workflow
259
+ `release.yml`, environment left empty.
260
+
261
+ ## License
262
+
263
+ MIT
@@ -0,0 +1,219 @@
1
+ # mediasense
2
+
3
+ **Give Claude ears and eyes.** Paste a TikTok, YouTube or Instagram link (or point at a file) in Claude
4
+ Code or Claude Desktop and ask in plain language. Claude can then summarize the video, explain what
5
+ happens in it, find the moment something is said, or edit it.
6
+
7
+ ```text
8
+ you: summarize this https://www.tiktok.com/@someone/video/7350…
9
+ you: what does he show at 0:30? and what tool is he talking about?
10
+ you: clean up ~/Desktop/podcast.m4a — remove the "um"s and long pauses
11
+ you: make short captions for ~/Videos/reel.mp4
12
+ you: put intro.mp3 under the first 5 seconds of talk.mp4, ducked
13
+ ```
14
+
15
+ ![mediasense in Claude: a TikTok link is downloaded, transcribed and summarized with timestamps](docs/demo.gif)
16
+
17
+ <sub>Real output for a 17-second TikTok by @elim.doc, shown with the creator's permission. Regenerate the
18
+ animation with `python docs/make_demo.py`.</sub>
19
+
20
+ mediasense runs **on your computer**: it downloads the link, transcribes speech in ~99 languages with a
21
+ timestamp for every word, picks key frames at scene changes, and hands Claude a transcript, a shot list
22
+ and contact-sheet images. Nothing is uploaded anywhere.
23
+
24
+ [Português 🇧🇷](README.pt-BR.md)
25
+
26
+ ## Setup
27
+
28
+ **Windows** – paste in PowerShell:
29
+
30
+ ```powershell
31
+ irm https://raw.githubusercontent.com/joaoestella/mediasense/main/install.ps1 | iex
32
+ ```
33
+
34
+ **macOS / Linux** – paste in a terminal:
35
+
36
+ ```bash
37
+ curl -LsSf https://raw.githubusercontent.com/joaoestella/mediasense/main/install.sh | sh
38
+ ```
39
+
40
+ Then **quit Claude Desktop completely** (tray/menu-bar icon → Quit), open it again and ask
41
+ *"summarize this video: <link>"*. The first transcription downloads the speech model (≈ 500 MB).
42
+
43
+ <details>
44
+ <summary>Prefer to read the script before running it?</summary>
45
+
46
+ ```powershell
47
+ irm https://raw.githubusercontent.com/joaoestella/mediasense/main/install.ps1 -OutFile install.ps1
48
+ notepad install.ps1
49
+ powershell -ExecutionPolicy Bypass -File .\install.ps1
50
+ ```
51
+
52
+ (macOS/Linux: `curl -LsSfO …/install.sh`, read it, then `sh install.sh`.)
53
+
54
+ The installer only installs what is missing — Python 3.12 and FFmpeg via `winget` (Homebrew/apt on
55
+ macOS/Linux) and `pipx` via pip — then `pipx install`s mediasense from this repository and runs
56
+ `mediasense setup`. It stops at the first failed step.
57
+ </details>
58
+
59
+ <details>
60
+ <summary>Manual setup (no script)</summary>
61
+
62
+ ```powershell
63
+ winget install ffmpeg # macOS: brew install ffmpeg · Linux: sudo apt install ffmpeg
64
+ python -m pip install --user pipx
65
+ python -m pipx ensurepath # then close and reopen the terminal
66
+ python -m pipx install "mediasense[all]"
67
+ mediasense setup -n # preview what setup will change
68
+ mediasense setup
69
+ mediasense doctor
70
+ ```
71
+
72
+ Use `python -m pipx …` rather than plain `pipx` right after installing it: the `pipx` command only
73
+ appears on PATH in a new terminal. No Git needed.
74
+ </details>
75
+
76
+ <details>
77
+ <summary>One-click Claude Desktop extension (experimental)</summary>
78
+
79
+ Download **[mediasense.mcpb](https://github.com/joaoestella/mediasense/releases/latest/download/mediasense.mcpb)**
80
+ and double-click it (or drag it into Claude Desktop → Settings → Extensions). No Python, pipx or
81
+ FFmpeg needed: Claude Desktop sets up Python by itself, and FFmpeg is downloaded on first use. The
82
+ first start takes a few minutes while it installs everything. This uses Claude Desktop's new "UV"
83
+ extension type, so if it doesn't work on your version, use the installer above.
84
+ </details>
85
+
86
+ ### What `mediasense setup` changes
87
+
88
+ - **Claude Desktop:** adds one entry, `mcpServers.mediasense`, to `claude_desktop_config.json`
89
+ (`%APPDATA%\Claude\` – or `%LOCALAPPDATA%\Claude-Data\claude_…\` for the Microsoft Store app –
90
+ `~/Library/Application Support/Claude/` on macOS, `~/.config/Claude/` on Linux; Claude Desktop →
91
+ Settings → Developer → Edit Config opens the one your app uses). Everything else in the file is kept, and the previous file is saved next to it as
92
+ `claude_desktop_config.json.<date>.bak`. If the file isn't valid JSON, setup stops without touching it.
93
+ - **Claude Code** (if installed): runs `claude mcp add --scope user mediasense -- <path>\mediasense mcp`.
94
+ - Nothing else. `mediasense setup -n` shows the exact changes without making them; `--desktop` or
95
+ `--code` limits it to one app. To undo: remove the `mediasense` entry from the config file and run
96
+ `claude mcp remove mediasense --scope user`.
97
+
98
+ Updating on Windows and pipx says a file "is being used by another process"? Claude Desktop is still
99
+ running the old server: `Get-Process mediasense | Stop-Process -Force`, then install again (the
100
+ installer script does this for you).
101
+
102
+ Something not working? `mediasense doctor` checks FFmpeg, the speech model, the GPU, link downloads and
103
+ the Claude connection.
104
+
105
+ ### Teach Claude when to use it (recommended)
106
+
107
+ mediasense comes with a **skill**: a short guide that makes Claude reach for mediasense whenever you
108
+ paste a video link, instead of trying to open the page (TikTok & co. block that).
109
+
110
+ - **Claude Code:** installed automatically by `mediasense setup`.
111
+ - **Claude Desktop / claude.ai:** download
112
+ [mediasense-skill.zip](https://github.com/joaoestella/mediasense/releases/latest/download/mediasense-skill.zip)
113
+ (the installer also saves it to `Downloads/mediasense/`), then in Claude open **Settings → Skills** and
114
+ upload it. One time only; it syncs to all your devices.
115
+
116
+ > **Note:** Claude Desktop sends files you attach in the chat to the model, not to your computer, so give
117
+ > mediasense a **link or a file path** instead (in Claude Code you can drag the file into the terminal).
118
+
119
+ ### Slash commands
120
+
121
+ The server adds ready-made prompts. In Claude Code they appear as `/mcp__mediasense__summarize` and so on.
122
+
123
+ | Prompt | Does |
124
+ |---|---|
125
+ | `summarize` | gist, key points with timestamps, steps, names and links, call to action |
126
+ | `explain_video` | shot-by-shot explanation, plus how the video is built (hook, structure) |
127
+ | `clean_up` | remove fillers and long pauses, show the plan first, render after your OK |
128
+ | `subtitles` | SRT captions, standard or short 1–3-word style for vertical video |
129
+
130
+ ### Tools Claude gets
131
+
132
+ | Tool | What it does |
133
+ |---|---|
134
+ | `understand_media` | **one call**: download link, transcribe, key frames + speech per shot, post title/description |
135
+ | `transcribe` | speech → `<file>.transcript.json` with word timestamps; `vocabulary` fixes brand names |
136
+ | `read_transcript`, `search_transcript` | read a time range or find every time a phrase is said |
137
+ | `plan_edit`, `render_edit` | cut phrases, passages, fillers, silences or ranges; preview, then render |
138
+ | `export_transcript` | SRT, VTT, TXT, CSV, JSON |
139
+ | `place_audio` | insert a clip at a timestamp (mix / duck / replace) |
140
+ | `watch_video`, `get_frame` | contact sheets, or one frame at a given time |
141
+ | `media_info` | duration, resolution, fps, streams |
142
+ | `check_job` | result of long work: new videos and the first run reply "still working" and finish in the background |
143
+
144
+ Long work never hits Claude's tool time limit: if a video takes more than ~30 s (a long video on a
145
+ CPU, or the very first run while the speech model downloads), the tool answers "still working" with a
146
+ progress percentage and Claude checks back with `check_job` until it's done.
147
+
148
+ All tools accept a file path **or a link**. Links are downloaded once to `~/Downloads/mediasense`
149
+ (change with `MEDIASENSE_HOME`) and reused.
150
+
151
+ ## Command line
152
+
153
+ Everything also works without Claude:
154
+
155
+ ```bash
156
+ mediasense understand "https://youtu.be/…" # transcript + shots + metadata, as text
157
+ mediasense transcribe talk.mp4 -l pt --vocab "Cloudflare, Claude" --also srt
158
+ mediasense search talk.transcript.json "next quarter"
159
+ mediasense edit talk.mp4 --fillers --silences 0.7 -n # -n = only show the plan
160
+ mediasense edit talk.mp4 --fillers --silences 0.7 --srt --edl --fcpxml
161
+ mediasense edit talk.mp4 --cut-between "let me check" "okay so" --cut-range 12:03-12:40
162
+ mediasense export talk.transcript.json captions.srt --words-per-cue 2
163
+ mediasense place video.mp4 voiceover.wav --at 0:12.5 --mode duck
164
+ mediasense storyboard reel.mp4
165
+ mediasense fetch "https://www.tiktok.com/@…/video/…"
166
+ ```
167
+
168
+ Edits never touch the original: results are written as `<name>.edited.*` / `<name>.placed.*`.
169
+ EDL opens in Premiere, Resolve and Avid; FCPXML in Final Cut Pro and Resolve.
170
+
171
+ ## Good to know
172
+
173
+ - **Names and jargon.** Whisper may write "Cloud Fair" for Cloudflare. Pass `--vocab` (Claude does this
174
+ automatically when it can infer the names from the title or the screen).
175
+ - **Fillers.** Whisper tends to leave hesitations out; transcribe with `--verbatim` when you want to cut
176
+ them. Real words are protected per language ("um" is an article in Portuguese, so it is never cut
177
+ there). Ambiguous words like "like", "tipo" or "né" are only removed if you list them.
178
+ - **Speed.** Everything works on a plain CPU: short clips take seconds, a few minutes of audio takes
179
+ about as long as the audio with the default `small` model (`base` is faster, `medium` more accurate).
180
+ No GPU? `--backend openai` sends the audio to an OpenAI-compatible transcription API instead
181
+ (fast on any machine, but the audio leaves your computer).
182
+ - **NVIDIA GPU (optional, much faster).** mediasense uses it automatically once the CUDA libraries are
183
+ present; no CUDA toolkit needed:
184
+
185
+ ```bash
186
+ python -m pipx inject mediasense nvidia-cublas-cu12 "nvidia-cudnn-cu12>=9,<10" nvidia-cuda-runtime-cu12
187
+ ```
188
+
189
+ (≈ 1.5 GB; needs a driver that supports CUDA 12 – `mediasense doctor` checks both). Restart Claude
190
+ Desktop afterwards.
191
+ - **Word timing** is approximate (0.1–0.2 s). For tighter cuts and speaker labels use
192
+ `--backend whisperx` (`pip install "mediasense[whisperx]"`).
193
+ - Downloading from links follows each site's terms. Use it for content you're allowed to download.
194
+
195
+ ## Development
196
+
197
+ ```bash
198
+ git clone https://github.com/joaoestella/mediasense && cd mediasense
199
+ pip install -e ".[dev,mcp]"
200
+ pytest
201
+ ```
202
+
203
+ The tests build synthetic audio/video with FFmpeg and use fake model and downloader libraries, so they
204
+ run in seconds with nothing to download. Ideas welcome: more filler words for your language, a
205
+ one-click Claude Desktop extension (`.mcpb`), and a GUI.
206
+
207
+ ## Releasing
208
+
209
+ 1. Bump `version` in `pyproject.toml` and `src/mediasense/__init__.py`, commit.
210
+ 2. `git tag vX.Y.Z && git push origin vX.Y.Z`. The Release workflow publishes to PyPI and creates a
211
+ GitHub release with the wheel, `mediasense-skill.zip` and `mediasense.mcpb`.
212
+
213
+ One-time PyPI setup (trusted publishing, no token): on pypi.org → *Your account → Publishing → Add a
214
+ new pending publisher*: project `mediasense`, owner `joaoestella`, repository `mediasense`, workflow
215
+ `release.yml`, environment left empty.
216
+
217
+ ## License
218
+
219
+ MIT