yueying
Deixe a IA assistir vídeos: arquivos locais ou URLs do YouTube/Bilibili -> transcrição com timestamps + folhas de contato de keyframes. Totalmente offline (legendas da plataforma primeiro, local faster-whisper caso contrário), ffmpeg incluído, sem chave de API. Seis ferramentas: watch_video, get_transcript, search_transcript, get_frames, get_frame_at, list_videos. Instalação: uvx yueying mcp
Documentação
yueying — deixe a IA assistir vídeos
Aponte o Claude, o Cursor ou qualquer cliente MCP para um vídeo e receba uma transcrição com timestamps e folhas de contato com keyframes — offline, sem chave de API. Arquivos locais primeiro; URLs (YouTube, Bilibili, Douyin, Xiaohongshu, TikTok, Vimeo, …) são vídeos que você tem direito de processar, baixados via yt-dlp em até 720p e excluídos após o processamento por padrão.
Yueying (阅影) significa "ler vídeo". Um único pacote oferece um servidor MCP, uma CLI e uma habilidade de agente.
O que você obtém

Claude Desktop com yueying conectado: cole um link, aguarde cerca de quarenta segundos e receba o vídeo de volta como
anotações com timestamps. Este vídeo possui legendas, então o reconhecimento de fala nunca foi executado, e o modelo pediu
apenas a transcrição. Keyframes e folhas de contato retornam via get_frames quando ele precisa ver
a tela. Vídeo de demonstração: GitInGifs: Git Branches por GitLab, CC BY.

Folha de contato de um clipe de demonstração de 24 segundos (quatro capturas de tela do aplicativo com narração em chinês). O rótulo amarelo em cada bloco é o número do keyframe e o timestamp; o modelo os cita de volta para você.
A transcrição do mesmo clipe — reconhecimento de fala local, idioma detectado automaticamente como chinês:
[00:00] 这是阅读,一个安静的桌面小说阅读器。整本书连续滚动,按段落记住进度。
第二个画面是桌面模式,窗口变透明,只留文字浮在桌面上。
第三个画面是伪装皮肤,一键变成代码编辑器。
最后是伪装成表格的样子。
(O aplicativo se chama 月读; o ASR ouviu o homófono 阅读. O reconhecimento de fala faz isso com nomes — o modelo corrige a partir do texto na tela nos quadros.)
Cada vídeo vira uma pasta:
report.md index for the model: metadata, chapters, contact sheets, keyframes, transcript
transcript.txt paragraphs with [mm:ss] timestamps
transcript.srt subtitles for any player
grid_01.jpg … 3x3 contact sheets, 9 keyframes each, in time order
frames/ full-size keyframes, e.g. f003_00m15s.jpg
manifest.json machine-readable result (paths, segments, chapters, options)
Por que yueying
- Legendas primeiro, Whisper apenas quando necessário. Legendas da plataforma são usadas quando existem. Caso contrário, faster-whisper local:
large-v3-turboem uma GPU NVIDIA,smallem CPU, com fallback automático para CPU — nada é enviado, sem chave. - ffmpeg incluído. Funciona no Windows 11 imediatamente (imageio-ffmpeg); sem ajustes de PATH.
- Eficiente em tokens. Keyframes são capturados em mudanças de cena, quase duplicados são descartados e empacotados em folhas de contato 3x3 com timestamps gravados. Uma folha ≈ 1–2K tokens para nove momentos; uma transcrição com
[mm:ss]parágrafos. - Plataformas chinesas e o resto. Bilibili (multipartes, coleções, vídeos de membros com seu login do navegador), Douyin, Xiaohongshu — e YouTube, TikTok, Vimeo, X e todos os outros sites do yt-dlp.
- Zero chaves de API, zero telemetria. O único tráfego de rede é o site de vídeo que você indicar e um download do modelo Whisper. Veja a política de privacidade.
Benchmark: um vídeo de 6 minutos do Bilibili → relatório em ~90 s em um laptop RTX 5060; em CPU com model=small espere ~1–2 min por 10 min de fala.
Início rápido
- Instale uv (Python não é necessário):
winget install astral-sh.uv # Windows brew install uv # macOS curl -LsSf https://astral.sh/uv/install.sh | sh # Linux / macOS - Aqueça e verifique tudo uma vez (instala o pacote, testa a GPU, baixa o modelo de fala, executa um teste rápido de 2 segundos e imprime a configuração para colar):
uvx yueying mcp --setup - Adicione o servidor ao seu cliente (abaixo) e então pergunte: "Assista C:\videos\lecture3.mp4 e transforme os passos em anotações" ou "O que este vídeo diz sobre docker compose: https://www.bilibili.com/video/BV…".
Claude Desktop
%APPDATA%\Claude\claude_desktop_config.json (Windows) · ~/Library/Application Support/Claude/claude_desktop_config.json (macOS). Saia e reabra o Claude completamente depois.
{ "mcpServers": { "yueying": { "command": "uvx", "args": ["yueying", "mcp"], "env": { "PYTHONUTF8": "1" } } } }
Nota para Windows: o Claude Desktop nem sempre enxerga seu PATH — se o servidor falhar ao iniciar ("spawn uvx ENOENT"), use o caminho absoluto, ex.: "command": "C:\\Users\\<you>\\.local\\bin\\uvx.exe" (where uvx imprime isso). Logs: %APPDATA%\Claude\logs\mcp-server-yueying.log (~/Library/Logs/Claude/ no macOS). Mantenha wait_seconds no padrão ali; veja a regra RUNNING.
Claude Code
claude mcp add --transport stdio --scope user yueying --env PYTHONUTF8=1 -- uvx yueying mcp
Ou coloque o .mcp.json deste repositório em um projeto (ele vem com "timeout": 1800000 para que uma única chamada watch_video possa aguardar um vídeo longo). Para aumentar o timeout de ferramentas do Claude Code globalmente, defina MCP_TOOL_TIMEOUT=1800000 (ms) no seu ambiente. O repositório também é um plugin do Claude Code (.claude-plugin/plugin.json: servidor + habilidade).
Cursor
Clique no selo Add to Cursor acima, ou coloque o mesmo JSON em ~/.cursor/mcp.json (global) ou .cursor/mcp.json (projeto):
{ "mcpServers": { "yueying": { "command": "uvx", "args": ["yueying", "mcp"], "env": { "PYTHONUTF8": "1" } } } }
Cline
MCP Servers → Configure (cline_mcp_settings.json). timeout está em segundos; as cinco ferramentas somente leitura são seguras para aprovação automática. Instruções passo a passo para agentes: llms-install.md.
{
"mcpServers": {
"yueying": {
"type": "stdio",
"command": "uvx",
"args": ["yueying", "mcp"],
"env": { "PYTHONUTF8": "1" },
"timeout": 1800,
"autoApprove": ["get_transcript", "search_transcript", "get_frames", "get_frame_at", "list_videos"]
}
}
}
Windsurf
~/.codeium/windsurf/mcp_config.json:
{ "mcpServers": { "yueying": { "command": "uvx", "args": ["yueying", "mcp"], "env": { "PYTHONUTF8": "1" } } } }
VS Code (modo agente do Copilot)
Clique no selo Install in VS Code acima, ou crie .vscode/mcp.json (observe a chave raiz servers):
{ "servers": { "yueying": { "type": "stdio", "command": "uvx", "args": ["yueying", "mcp"], "env": { "PYTHONUTF8": "1" } } } }
Links diretos para hosts que aceitam esquemas de URL personalizados: cursor://anysphere.cursor-deeplink/mcp/install?name=yueying&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyJ5dWV5aW5nIiwibWNwIl0sImVudiI6eyJQWVRIT05VVEY4IjoiMSJ9fQ== e vscode:mcp/install?%7B%22name%22%3A%22yueying%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22yueying%22%2C%22mcp%22%5D%2C%22env%22%3A%7B%22PYTHONUTF8%22%3A%221%22%7D%7D.
Sem uv (pip / pipx) e Windows com um clique
pip install yueying # or: pipx install yueying
yueying mcp --setup # prints a config with the absolute path of the yueying-mcp executable
Use esse caminho absoluto como "command" sem args (Windows: ...\Scripts\yueying-mcp.exe; também funciona como python -m yueying mcp). Usuários de Windows sem ferramentas Python podem dar dois cliques em install.cmd a partir de um checkout: ele cria %LOCALAPPDATA%\yueying\venv, instala a habilidade do Claude Code, executa yueying mcp --setup e imprime o bloco JSON com o caminho correto.
GPU
uvx --from "yueying[cuda]" yueying mcp # NVIDIA: adds the CUDA runtime wheels (cuBLAS, cuDNN)
pip install "yueying[cuda]"
Dispositivo e modelo são escolhidos automaticamente (model=auto: large-v3-turbo em CUDA, small em CPU); se o teste de GPU falhar, o reconhecimento cai para CPU sozinho.
Docker
docker build -t yueying .
docker run --rm -i -v yueying-data:/data -v "$PWD/videos:/videos:ro" yueying
A imagem é somente CPU (contêineres não recebem GPU por padrão), então ela usa o modelo small por padrão.
Monte seus vídeos como somente leitura e dê caminhos de contêiner às ferramentas (/videos/lesson.mp4); os resultados e
os pesos do Whisper baixados ficam no volume /data. Em uma configuração de cliente, o command é
docker e args são ["run", "--rm", "-i", "-v", "yueying-data:/data", "-v", "/your/videos:/videos:ro", "yueying"].
Ferramentas
| Ferramenta | Quando o agente a usa | O que retorna | Limites |
|---|---|---|---|
watch_video(video, mode="full", language="auto", model="auto", frame_interval_seconds=None, cookies_from_browser=None, output_dir=None, refresh=False, wait_seconds=45, max_chars=12000) | Primeira chamada para qualquer vídeo: um caminho local absoluto ou uma URL. mode: full (transcrição + keyframes), transcript, frames. | Visão geral DONE: título, fonte, duração, fonte do texto, pasta, arquivos, capítulos, intervalos das folhas de contato, transcrição em [mm:ss] parágrafos — ou RUNNING com estágio/percentual/ETA, ou ERROR com uma dica em inglês simples. | Bloqueia por até wait_seconds (0–1500). Transcrição truncada em max_chars com um tempo de início get_transcript. Em cache por vídeo; refresh=true reprocessa. |
get_transcript(video, start="0", end=None, format="paragraphs", max_chars=8000) | A visão geral foi truncada, um intervalo de tempo específico ou exportação de legendas (format="srt"). | Cabeçalho + [mm:ss] parágrafos / [mm:ss-mm:ss] segmentos / blocos SRT; TRUNCATED — next_start="…" quando cortado. | max_chars 1000–100000. Tempos: segundos, mm:ss, h:mm:ss. |
search_transcript(video, query, context_seconds=15, limit=10) | "Quando ele menciona X?" | Correspondências com tempo, frases ao redor, número do keyframe mais próximo e número da folha de contato. | Termos separados por espaço, qualquer correspondência, mais termos classificam mais alto; limit ≤ 50. |
get_frames(video, kind="grids", start=1, count=2, max_width=1280) | Ver o que está na tela: folhas de contato primeiro (grids), keyframes individuais (frames) apenas para detalhes. | Caminho absoluto + JPEG por imagem, em ordem de tempo; Next: get_frames(start=…) quando houver mais. | ≤ 3 imagens por chamada (padrão 2, mantenha ≤ 2 no Claude Desktop); ~150 KB por folha em 1280 px. |
get_frame_at(video, time, max_width=960) | Ler código, um slide, um gráfico ou interface em um momento específico. | O quadro exato (extraído da fonte quando o arquivo local ainda existe) ou o keyframe em cache mais próximo, além dos parágrafos falados naquele momento. | Uma imagem, ~100 KB em 960 px. |
list_videos(limit=20) | O usuário se refere a um vídeo anterior ou para verificar o uso de disco. | Tabela: video_id, título, duração, fonte do texto, data, tamanho, pasta; trabalhos em execução. | Instantâneo, somente leitura. |
video para as ferramentas de leitura aceita o video_id de watch_video/list_videos, a pasta de resultados ou o mesmo caminho/URL que você deu a watch_video.
A regra RUNNING
O processamento pode levar minutos, e a maioria dos hosts limita uma chamada de ferramenta a cerca de um minuto. Então watch_video espera no máximo wait_seconds e então responde RUNNING video_id=… · stage 2/4 speech recognition 40% · elapsed 46 s · est. ~1 min remaining. O agente simplesmente chama watch_video novamente com o mesmo video — ele se reconecta ao mesmo trabalho (opções são ignoradas enquanto ele roda; refresh=true reinicia). wait_seconds recomendado:
| Host | wait_seconds | Por quê |
|---|---|---|
| Claude Desktop | 45 (padrão) | timeout duro do cliente ~60 s |
| Cursor | 45 (padrão) | 60–120 s |
| Claude Code | até 1500 | com .mcp.json timeout / MCP_TOOL_TIMEOUT = 1800000 ms |
| Cline | até 1500 | com "timeout": 1800 (s) |
Notificações de progresso são enviadas a cada 1,5 s para hosts que as exibem. Um vídeo é processado por vez por servidor; solicitações extras entram na fila.
Primeira execução: o primeiro reconhecimento de fala baixa um modelo Whisper uma vez (~480 MB small em CPU, ~1,6 GB large-v3-turbo em GPU). uvx yueying mcp --setup faz isso antecipadamente; caso contrário, a linha RUNNING diz "first run downloads ~… this can take several minutes".
Onde os arquivos vão
Raiz: $YUEYING_OUT_DIR se definido, senão ~/yueying_out. Uma entrada por vídeo, nomeada <slug>-<video_id> (yt-<id>, bili-<BV> ou o nome do arquivo) — nunca renomeada; o título fica em manifest.json.
~/yueying_out/
└── bili-BV1xx-3f9a2c1e/
├── report.md transcript.txt transcript.srt manifest.json
├── grid_01.jpg … grid_07.jpg
├── frames/ f001_00m02s.jpg … (+ frames/extra/ for get_frame_at)
├── .job only while a job runs
└── _download/ only with YUEYING_KEEP_SOURCE=1
| Variável de ambiente | Significado | Padrão |
|---|---|---|
YUEYING_OUT_DIR | pasta raiz para resultados (absoluta, ~ ok) | ~/yueying_out |
YUEYING_MODEL | padrão para o parâmetro model | auto |
YUEYING_DEVICE | auto / cuda / cpu | auto |
YUEYING_LANG | idioma do report.md escrito pelo servidor (en/zh) | en |
YUEYING_COOKIES_FROM_BROWSER | navegador padrão para cookies (chrome, edge, firefox, …) | não definido |
YUEYING_KEEP_SOURCE | 1 mantém a fonte baixada em ≤720p em _download/ (permite quadros de momento exato para URLs) | não definido |
YUEYING_MAX_JOBS | pipelines rodando ao mesmo tempo por servidor | 1 |
YUEYING_JOB_TIMEOUT | limite rígido por vídeo, em segundos | 7200 |
HF_HOME | cache do Hugging Face (os pesos do Whisper ficam aqui) | padrão do HF |
HF_ENDPOINT | espelho, ex.: https://hf-mirror.com | huggingface.co |
PYTHONUTF8 | defina como 1 no Windows para evitar mojibake | — |
Orçamento de disco: ≈ 25 MB por hora de vídeo; 300–600 MB/h a mais com YUEYING_KEEP_SOURCE=1. Nada é excluído automaticamente — list_videos mostra tamanhos; exclua uma pasta para liberar espaço; watch_video(refresh=true) reprocessa um vídeo. Editar um arquivo local muda seu tamanho/mtime e, portanto, gera uma nova entrada.
Fontes suportadas
- Arquivos locais: qualquer coisa que o ffmpeg leia — mp4, mkv, mov, webm, avi, flv, ts e áudio (mp3, m4a, wav, …). Entrada somente de áudio gera uma transcrição sem quadros.
- URLs: todos os sites suportados pelo yt-dlp. Baixados em ≤720p e excluídos após o processamento, a menos que
YUEYING_KEEP_SOURCE=1. - Bilibili: sem login, o Bilibili serve 480p — suficiente para slides e código. Para HD ou vídeos exclusivos de membros, passe
cookies_from_browser="chrome"(ouedge,firefox,brave,chromium,safari); no Windows, feche o Chrome primeiro, ele bloqueia o banco de dados de cookies. Vídeos em várias partes e coleções: linksp=são entradas separadas; o--allda CLI processa todos. - Não para transmissões ao vivo ou imagens. Links curtos (
b23.tv,v.douyin.com) são processados, mas não deduplicados contra sua forma longa (o servidor nunca resolve URLs por conta própria).
Também uma CLI e uma habilidade de agente
yueying video.mp4
yueying "https://www.bilibili.com/video/BVxxxx" --ui-lang en
yueying "https://www.youtube.com/watch?v=xxxx" --out ./notes/xxx
yueying lesson1.mp4 lesson2.mp4 "https://www.bilibili.com/video/BVyyyy" # several at once, one folder each + index.md
yueying "https://www.bilibili.com/video/BVxxxx" --all # every part of a multi-part video / collection
yueying --install-skill # Claude Code skill -> ~/.claude/skills/yueying
Saída padrão: ./yueying_out/<name>/ (pasta pai quando há várias entradas). As linhas de log da CLI e o report.md são em chinês por padrão (--ui-lang en para inglês); 0.3 mudará o padrão para inglês.
| Sinalizador | Significado |
|---|---|
--out DIR | pasta de saída (padrão ./yueying_out/<name>; a pasta pai quando há várias entradas) |
--all | quando a URL é um vídeo de múltiplas partes / coleção / playlist do Bilibili, processa todas as entradas (padrão: apenas a primeira) |
--lang zh | código do idioma falado (zh, en, ja, …); padrão: detecção automática |
--model auto | modelo Whisper: auto / tiny / base / small / medium / large-v3 / large-v3-turbo (padrão da CLI). auto = large-v3-turbo em GPU NVIDIA, small em CPU |
--device cpu | forçar CPU (auto / cuda / cpu) |
--interval 3 | aproximadamente um quadro-chave a cada N segundos. Padrão por duração: 2 s abaixo de 1 min, 3 s abaixo de 3 min, 6 s abaixo de 10 min, 12 s abaixo de 30 min, 20 s além disso |
--frames 30 | número máximo de quadros-chave (padrão por duração, limite 150; 300 com --interval) |
--scene 0.2 | sensibilidade a mudanças de cena 0–1, menor = mais sensível (padrão 0.3) |
--no-dedupe | manter quadros quase idênticos ao anterior (padrão: descartá-los: < 2 % dos pixels da miniatura alterados) |
--no-asr | sem reconhecimento de fala mesmo sem legendas (apenas imagens) |
--no-frames | sem quadros-chave (apenas texto) |
--force-asr | executar reconhecimento de fala mesmo quando existem legendas |
--cookies-from-browser chrome | baixar com o login do seu navegador (vídeos HD / de membros do Bilibili, YouTube com restrição de login) |
--keep | manter o vídeo de origem baixado |
--ui-lang en | idioma dos títulos e rótulos do report.md: zh (padrão) ou en |
--json | imprimir uma linha do manifesto JSON no final (para scripts) |
--install-skill | instalar a habilidade do agente em ~/.claude/skills/yueying |
mcp | executar o servidor MCP (mcp --setup, mcp --check, mcp --version) |
A habilidade (src/yueying/skill/SKILL.md) diz a um agente de codificação para preferir as ferramentas MCP quando presentes e, caso contrário, executar a CLI e ler report.md além das folhas de contato. Ferramentas que suportam o padrão Agent Skills podem copiar ~/.claude/skills/yueying/SKILL.md para sua própria pasta de habilidades.
Comparação com projetos semelhantes (setembro de 2026)
| yueying | claude-video | claude-real-video | mcp-video-analyzer | |
|---|---|---|---|---|
| Servidor MCP | sim | não (apenas habilidade) | não (habilidade) | sim (Node) |
| Reconhecimento de fala offline | sim — legendas primeiro, faster-whisper local caso contrário | fallback de Whisper em nuvem | ASR primeiro | whisper instalado separadamente |
| Detecção automática de GPU + fallback de CPU | sim | – | – | – |
| ffmpeg incluído | sim | – | ffmpeg manual | – |
| Testado no Windows | sim (Windows 11) | – | – | – |
| Folhas de contato (3x3) | sim | – | – | – |
| Carimbos de data/hora nos quadros | sim | – | – | – |
| Bilibili / Douyin / Xiaohongshu | sim | – | – | – |
"–" significa que o projeto não anunciava o recurso quando olhamos; verifique os READMEs deles, podem ter evoluído.
Política de privacidade
O yueying não coleta nada e não tem telemetria, análises, relatórios de falhas ou verificações de atualização. Todo o processamento é local. As únicas conexões de rede são (1) ao site de vídeo da URL que você passa, via yt-dlp, e (2) ao Hugging Face (ou HF_ENDPOINT) para baixar um modelo Whisper uma vez. As saídas são armazenadas na sua pasta até você excluí-las. A transcrição e quaisquer quadros solicitados são enviados apenas ao modelo que seu cliente MCP está configurado para usar — essa transferência é regida pelos termos do seu cliente e provedor, não pelo yueying. Perguntas: GitHub issues. Texto completo: docs/privacy.md.
Solução de problemas / FAQ
- "Nenhum resultado recebido" no Claude Desktop. Mantenha
wait_secondsem 45 (o agente então re-chamawatch_video) e executeuvx yueying mcp --setupuma vez para que a primeira chamada não seja também o download do modelo. spawn uvx ENOENT/ servidor falha ao iniciar. O host não consegue ver seu PATH: use o caminho absoluto parauvx(where uvx/which uvx) ou parayueying-mcpcomo"command".- Janelas de console piscam no Windows. Atualize para 0.2.0+: processos filhos são iniciados sem janela. Se ainda os vir, você está executando uma instalação antiga (
uv cache clean yueying). - Mojibake /
?????em títulos. Adicione"env": { "PYTHONUTF8": "1" }à configuração do servidor (todos os trechos acima o incluem). - Erro 412 / "-352" do Bilibili. O site quer um login:
cookies_from_browser="edge"ou"chrome"(feche o Chrome primeiro no Windows). - YouTube "Faça login para confirmar que você não é um robô". Mesma correção:
cookies_from_browser. Também tente atualizar o yt-dlp:uv cache clean yueyingoupip install -U yt-dlp. - Lento na CPU.
model="small"já é a escolha automática sem GPU NVIDIA; usemode="frames"quando apenas as imagens importam, oumode="transcript"para pular quadros-chave. - Nomes, números e código errados na transcrição. Esperado com qualquer ASR — o agente é instruído a confiar no texto na tela; peça para
get_frame_ato momento. - Download do modelo lento ou bloqueado (China continental). Defina
HF_ENDPOINT=https://hf-mirror.comnoenvdo servidor (a CLI alterna para o espelho automaticamente quando huggingface.co está inacessível). - Erro de GPU (CUDA / cuDNN / memória insuficiente).
model="small"ouYUEYING_DEVICE=cpu; instale os wheels CUDA comyueying[cuda]. - Quer reprocessar com configurações diferentes.
watch_video(video=…, refresh=true, …)— ele encerra um trabalho em execução para aquele vídeo, exclui a entrada e recomeça.
Como funciona
video / URL ──► yt-dlp (≤720p) + platform subtitles
──► ffmpeg 16 kHz audio ──► faster-whisper (skipped when subtitles exist)
──► ffmpeg scene detection ──► keyframes (near-duplicates dropped)
──► Pillow: burn "#n mm:ss", pack 3x3 contact sheets
──► report.md · transcript.txt · transcript.srt · manifest.json
MCP client ──stdio──► mcp_server.py ──spawns──► python -m yueying.cli <video> --json --ui-lang en
│ parses the child's progress lines, long-polls, caches per video
└─► store.py (cache keys / folders) · query.py (paging, search, frames)
O processo do servidor nunca carrega yt-dlp, Whisper ou CUDA; todo o trabalho pesado roda em um processo filho que é encerrado junto com o servidor. Tudo vive em src/yueying/:
| Arquivo | Responsabilidade |
|---|---|
cli.py | entrada de linha de comando; executa o pipeline; despacho de subcomando mcp; --install-skill |
mcp_server.py | o servidor MCP: seis ferramentas, executor de trabalhos, análise de progresso, renderização DONE/RUNNING/ERROR, --setup |
store.py | raiz de saída, URLs canônicas, chaves de cache e nomes de pasta por vídeo, marcadores .job |
query.py | funções puras sobre um manifesto: paginação de transcrição, busca, quadro mais próximo, intervalos de folha de contato, redução de imagem |
models.py | nomes de modelos Whisper, tamanhos e repositórios Hugging Face (sem imports pesados) |
download.py | download via yt-dlp, escolha de idioma de legenda, listagem de playlist/coleção |
ffm.py | wrapper ffmpeg: sondagem, extração de áudio, legendas incorporadas, timeouts |
subs.py | análise de legendas srt / vtt / JSON do Bilibili, deduplicação de legendas automáticas do YouTube |
asr.py | transcrição faster-whisper, seleção GPU/CPU, modelo auto, fallbacks |
frames.py | detecção de cena, temporização de quadros, extração, deduplicação, carimbo de data/hora, folhas de contato |
report.py | report.md, arquivos de transcrição, manifest.json (rótulos zh/en), carregamento de manifesto |
skill/SKILL.md | a habilidade do agente |
Roadmap
- próximo —
.mcpbpacote de um clique para Claude Desktop, listagem no Smithery. - 0.3 — ferramentas
forget_video/ poda, inglês como idioma padrão de relatório da CLI,--all(playlists) via MCP.
Créditos
- faster-whisper, yt-dlp, imageio-ffmpeg, Pillow
- Carimbos de data/hora nas folhas de contato seguem video-vision-mcp; intervalos de quadros baseados em duração seguem video-analyzer-skill
Licença
MIT — veja LICENSE.
中文说明
阅影(yueying)让 AI 看懂视频。 给 Claude Desktop、Claude Code、Cursor 等支持 MCP 的工具一个本地视频文件或视频链接(B站 / YouTube / 抖音 / 小红书 …),它就能拿到带时间戳的文字稿和关键帧九宫格:字幕优先,没有字幕就本地 faster-whisper 识别,全程离线,不上传、不要 API key。链接通过 yt-dlp 以 ≤720p 下载,处理完默认删除原视频。完整文档见上方英文部分。
安装
# 1. 装 uv(不需要先装 Python)
winget install astral-sh.uv # Windows;macOS: brew install uv
# 2. 预热:安装、探测显卡、下载模型、跑 2 秒冒烟测试、打印配置
uvx yueying mcp --setup
不用 uv:pip install yueying(有 NVIDIA 显卡再加 pip install "yueying[cuda]"),然后 yueying mcp --setup 会打印 yueying-mcp 的绝对路径。Windows 也可以下载仓库后双击 install.cmd,它会建独立环境、装 Claude Code 技能、跑 --setup 并打印可粘贴的配置。
配置
Claude Desktop(%APPDATA%\Claude\claude_desktop_config.json,改完完全退出再打开;Windows 下 uvx 找不到就写绝对路径,如 C:\\Users\\<你>\\.local\\bin\\uvx.exe)、Cursor(~/.cursor/mcp.json)、Windsurf(~/.codeium/windsurf/mcp_config.json)都是同一段:
{ "mcpServers": { "yueying": { "command": "uvx", "args": ["yueying", "mcp"], "env": { "PYTHONUTF8": "1" } } } }
Claude Code 一行:
claude mcp add --transport stdio --scope user yueying --env PYTHONUTF8=1 -- uvx yueying mcp
Cline 在同一段里加 "type": "stdio"、"timeout": 1800,并把 get_transcript、search_transcript、get_frames、get_frame_at、list_videos 放进 autoApprove。VS Code 的 .vscode/mcp.json 根键是 servers 并加 "type": "stdio"。
六个工具
| 工具 | 用途 |
|---|---|
watch_video(video, mode, language, model, frame_interval_seconds, cookies_from_browser, output_dir, refresh, wait_seconds, max_chars) | 看一个视频:本地绝对路径或链接。返回 DONE(概览 + 文字稿)、RUNNING(进度,用同一个 video 再调一次即可继续等)或 ERROR(英文提示)。结果按视频缓存,refresh=true 重做 |
get_transcript(video, start, end, format, max_chars) | 按时间段读文字稿;format="srt" 导出字幕 |
search_transcript(video, query, context_seconds, limit) | 找「哪里提到了 X」,给出时间、上下文、最近的关键帧号和九宫格号 |
get_frames(video, kind, start, count, max_width) | 看画面:先看九宫格(grids),需要细节再看单帧(frames);每次最多 3 张 |
get_frame_at(video, time, max_width) | 看某一时刻:代码、PPT、图表、界面;本地文件还在就精确抽帧 |
list_videos(limit) | 列出处理过的视频(video_id、标题、时长、文字来源、日期、大小、目录)和正在跑的任务 |
Claude Desktop / Cursor 里 wait_seconds 保持默认 45;Claude Code / Cline 配好 timeout 后可以给到 1500,一次调用就等到结果。第一次语音识别要下载模型(CPU 约 480 MB 的 small,显卡约 1.6 GB 的 large-v3-turbo),--setup 会提前下好。
输出目录与环境变量
结果在 ~/yueying_out/<名字>-<video_id>/(YUEYING_OUT_DIR 可改),每个视频一个文件夹:report.md、transcript.txt、transcript.srt、grid_01.jpg …、frames/、manifest.json。约每小时视频 25 MB;不会自动删,删文件夹即可。常用环境变量:YUEYING_OUT_DIR(输出根目录)、YUEYING_MODEL(默认 auto:有 NVIDIA 显卡用 large-v3-turbo,否则 small)、YUEYING_DEVICE(auto/cuda/cpu)、YUEYING_LANG(服务端 report.md 语言,默认 en,中文写 zh)、YUEYING_KEEP_SOURCE=1(保留下载的原视频)、YUEYING_JOB_TIMEOUT(单个视频上限秒数,默认 7200)、PYTHONUTF8=1(Windows 防乱码)。
B站 cookie
不登录 B站 只给 480p,看 PPT 和代码够用;高清或会员视频传 cookies_from_browser="chrome"(或 edge),Windows 下先关掉 Chrome,否则读不到 cookie 数据库。遇到 412 / -352 也是同样的处理。
国内镜像
下载模型慢或被墙:在服务器配置的 env 里加 "HF_ENDPOINT": "https://hf-mirror.com"。命令行版在 huggingface.co 连不上时会自动切到镜像。
命令行用法
yueying 视频.mp4
yueying "https://www.bilibili.com/video/BVxxxx"
yueying "https://www.youtube.com/watch?v=xxxx" --out ./notes/xxx
yueying 第1课.mp4 第2课.mp4 "https://www.bilibili.com/video/BVyyyy" # 多个一起,各出各的文件夹 + index.md
yueying "https://www.bilibili.com/video/BVxxxx" --all # B站 分 P / 合集 全部处理
yueying --install-skill # 装 Claude Code 技能
默认输出 ./yueying_out/<视频名>/,日志和 report.md 默认中文(--ui-lang en 切英文)。常用参数:--lang zh 指定语言、--model small 换小模型(auto 自动选)、--device cpu、--interval 3 抽帧间隔、--frames 30 最多帧数、--scene 0.2 场景灵敏度、--no-dedupe 不去重、--no-asr 只要画面、--no-frames 只要文字、--force-asr 有字幕也识别、--cookies-from-browser chrome、--keep 保留原视频、--json 末尾打印一行 manifest。完整说明见上方英文表格。