{"id":9695209,"url":"https://github.com/buxuku/VideoSubtitleGenerator","last_synced_at":"2025-08-26T06:31:45.905Z","repository":{"id":239264038,"uuid":"734202337","full_name":"buxuku/VideoSubtitleGenerator","owner":"buxuku","description":"批量为本地视频生成字幕文件，并可将字幕文件翻译成其它语言， 跨平台支持 window, mac 系统","archived":false,"fork":false,"pushed_at":"2024-12-12T08:46:52.000Z","size":3011,"stargazers_count":605,"open_issues_count":3,"forks_count":46,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-12-21T07:03:01.591Z","etag":null,"topics":["subtitle","translate","whisper","whisper-cpp"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/buxuku.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-21T05:44:23.000Z","updated_at":"2024-12-21T02:19:17.000Z","dependencies_parsed_at":"2024-06-05T17:42:14.075Z","dependency_job_id":"79bd8de8-ef78-4723-be12-55f896ac02d4","html_url":"https://github.com/buxuku/VideoSubtitleGenerator","commit_stats":{"total_commits":12,"total_committers":3,"mean_commits":4.0,"dds":"0.41666666666666663","last_synced_commit":"de4960257cc0dc8de024d94cab08e457a23af313"},"previous_names":["buxuku/videosubtitlegenerator"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buxuku%2FVideoSubtitleGenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buxuku%2FVideoSubtitleGenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buxuku%2FVideoSubtitleGenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buxuku%2FVideoSubtitleGenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/buxuku","download_url":"https://codeload.github.com/buxuku/VideoSubtitleGenerator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231011331,"owners_count":18314774,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["subtitle","translate","whisper","whisper-cpp"],"created_at":"2024-05-15T12:02:16.615Z","updated_at":"2025-08-26T06:31:45.892Z","avatar_url":"https://github.com/buxuku.png","language":"JavaScript","readme":"# 批量为视频生成字幕文件，并翻译成其它语言\n\n\u003e [!IMPORTANT]  \n\u003e 🧨 💥 🎉 本项目是一个命令行工具，但非常荣幸得到了很多朋友的支持，也给我了很大的鼓舞，因此，我基于它制作了一款客户端工具，让大家能够更加方便地使用，也方便一部分不熟悉代码配置的朋友也能使用该工具。\n\u003e \n\u003e 欢迎大家移步 [SmartSub](https://github.com/buxuku/SmartSub) 以获得更加便捷的使用体验\n\u003e ![image](https://github.com/buxuku/video-subtitle-master/raw/main/resources/preview.png)\n\n\n做这个小工具的初衷：\n\n自己有一大批外文视频，没有字幕，希望能够添加字幕文件，同时也能够将字幕文件翻译成中文， 同时希望能够通过批量处理的方式来减轻工作量。\n\n类似需求，有一批厂商已经提供到了支持，比如 讯飞听见， 网易见外 等，但这些在线服务都涉及到视频的上传动作，效率相对比较低下。\n\n希望能够找一个客户端工具，在本地来生成，试用了一些工具，依然不理想\n\n- Buzz 非 Store 版本没有对 apple silicon 做优化，字幕生成速度比较慢，也不支持翻译\n- MacWhisper 免费版本只支持单个生成，不支持批量，不支持翻译\n- WhisperScript 可以批量生成，但字幕文件需要手动一个个地保存，不支持翻译\n- memo.ac 做了 mac 下的性能优化，可以使用 GPU ，也支持翻译功能，非常棒的一款软件，但目前批量模式 bug 太多，无法正常使用\n\n最后想了一下，本地语音转文字，通常的做法就是使用目前最强的 whisper 模型来生成。那我的需求就比较简单了：\n\n- 通过 ffmpeg 从视频文件中提取出音频文件\n- 通过 whisper 模型将音频生成原语言的字幕文件\n- 调用翻译 API， 将原语言的字幕文件翻译成目标语言的字幕文件\n\n基于以上简单的思路和流程，就可以简单写一个小工具来批量处理本地的视频了。\n\n## 💥特性\n\n- 源语言字幕文件和目标语言字幕文件放在视频同目录下，方便播放时任意挂载字幕文件\n- 批量处理目录下面的所有视频文件\n- 可以只生成字幕，不翻译，方便批量为视频生成字幕\n- 支持火山引擎翻译\n- 支持百度翻译\n- 支持 deeplx 翻译 （批量翻译容易存在被限流的情况）\n- 支持 ollama 翻译\n- 自定义字幕文件名，方便兼容不同的播放器挂载字幕识别\n- 自定义翻译后的字幕文件内容，纯翻译结果，原字幕+翻译结果\n- 项目集成 `whisper.cpp`， 它对 apple silicon 进行了优化，有较快的生成速度\n- 项目集成了 `fluent-ffmpeg`, 无须安装 `ffmpeg`\n\n### ⬆️ 支持的模型\n\n```\ntiny.en\ntiny\nbase.en\nbase\nsmall.en\nsmall\nmedium.en\nmedium\nlarge-v1\nlarge-v2\nlarge-v3\n```\n\n## 翻译服务\n\n本项目的翻译能力是基于 **百度/火山/deeplx** 的翻译API来实现的，这些 API 的使用需要申请对的 KEY 和 SECRET， 因此，如果你需要使用到翻译服务，需要先申请一个 API 。\n\n具体的申请方法，可以参考 https://bobtranslate.com/service/ ， 感谢 [Bob](https://bobtranslate.com/) 这款优秀的软件。\n\n## 🔦使用\n\n1️⃣ 克隆本项目在本地\n\n```shell\ngit clone https://github.com/buxuku/VideoSubtitleGenerator.git\n```\n\n2️⃣ 在项目中执行 `yarn install` 或者 `npm install`\n\n```shell\ncd VideoSubtitleGenerator\nyarn install \n```\n\n3️⃣ 如果需要翻译，复制 `.env.local` 为 `.env` 在项目根目录，访文件用于配置翻译相关的 KEY 和 SECRET， 例如\n\n`BAIDU_` 开头的为百度翻译的配置\n\n`VOLC_` 开头的为火山翻译的配置\n\n`OLLAMA_` 开头的为 ollama 翻译的配置\n\n```shell\nBAIDU_KEY=2023120600190xxxx\nBAIDU_SECRET=PIbyKjEr1y8u18RZxxxx\nVOLC_KEY=AKLTMDUwZjY4MTZkNTFmN4M3ZjlkMzlmYzAzMTdlMDExxxx\nVOLC_SECRET=T0dRMllUUmpPREUzWWpjNE5HVm2Zamt4TlRObU9EUm1ORFk0T1dGbExxxx==\n\nOLLAMA_API_URL=http://localhost:11434\nOLLAMA_MODEL_NAME=llama3\nOLLAMA_PROMPT=Please translate the following content from ${sourceLanguage} to ${targetLanguage}, only return the translation result can be. \\n ${content}\n```\n\n4️⃣ 其余的配置在 `config.js` 文件中进行配置，每条配置均的详细的注释\n\n```js\n// 视频文件所在目录 如 /Users/demo/video\nexport const videoDir = './examples';\n\n/*\nwhisper.cpp 模型 支持以下\ntiny.en\ntiny\nbase.en\nbase\nsmall.en\nsmall\nmedium.en\nmedium\nlarge-v1\nlarge-v2\nlarge-v3\n */\nexport const whisperModel = 'base.en';\n\n// 翻译配置，视频原语言与翻译后的目标语言\nexport const translateConfig = {\n    sourceLanguage: 'en',\n    targetLanguage: 'zh',\n};\n\n// 支持的翻译服务商\nexport const supportedService = {\n    baidu: Symbol.for('baidu'),\n    volc: Symbol.for('volc'),\n    deeplx: Symbol.for('deeplx'),\n    ollama: Symbol.for('ollama'),\n};\n\n// 当前使用的翻译服务商，如果不配置，则不执行翻译流程\nexport const translateServiceProvider = supportedService.volc;\n\n// 翻译结果字幕文件内容配置\nexport const contentTemplateRuleMap = {\n    onlyTranslate: Symbol.for('onlyTranslate'), // 只输出翻译内容\n    sourceAndTranslate: Symbol.for('sourceAndTranslate'), // 输出原始字幕和翻译字幕， 原始字幕在上面\n    translateAndSource: Symbol.for('translateAndSource'), // 输出翻译后的字幕和原始字幕， 翻译字幕在上面\n};\n\n// 字幕文件内容模板 支持 ${sourceContent}, ${targetContent} 变量\nexport const contentTemplate = {\n    [contentTemplateRuleMap.onlyTranslate]: '${targetContent}\\n\\n',\n    [contentTemplateRuleMap.sourceAndTranslate]: '${sourceContent}\\n${targetContent}\\n\\n',\n    [contentTemplateRuleMap.translateAndSource]: '${targetContent}\\n${sourceContent}\\n\\n',\n};\n\n// 翻译内容输出模板规则，默认只输出翻译内容, 支持 contentTemplateRuleMap 内的规则\nexport const contentTemplateRule = contentTemplateRuleMap.onlyTranslate;\n\n// 原始字幕文件保存命名规则 支持 fileName, sourceLanguage, targetLanguage 变量\n// 如果为空，将不保存原始字幕文件\n// eg: '${fileName}.${sourceLanguage}' -\u003e 对于视频名为 text.mp4 的英文视频原始字幕文件名为 text.en.srt\nexport const sourceSrtSaveName = '${fileName}.${sourceLanguage}';\n\n// 翻译后的字幕文件保存命名规则 支持 fileName, sourceLanguage, targetLanguage 变量\nexport const targetSrtSaveName = '${fileName}.${targetLanguage}';\n```\n\n这里面的字幕内容和字幕文件名可以自定义配置，同时会将里面的 `${xxx}`变量转为对应的字符\n\n核心配置主要为以下几项\n\n#### 选择翻译服务商\n\n\n```js\n// 当前使用的翻译服务商，如果不配置，则不执行翻译流程\nexport const translateServiceProvider = supportedService.volc;\n```\n\n支持\n- supportedService.volc 火山翻译\n- supportedService.baidu 百度翻译\n- supportedService.deeplx deeplx 翻译\n- supportedService.ollama ollama 翻译\n\n#### 翻译结果的配置\n\n```js\n// 翻译内容输出模板规则，默认只输出翻译内容, 支持 contentTemplateRuleMap 内的规则\nexport const contentTemplateRule = contentTemplateRuleMap.onlyTranslate;\n```\n\n支持以下几种设置模式\n\n##### contentTemplateRuleMap.onlyTranslate\n\n只保留翻译后的结果内容，如\n\n```\n1\n00:00:00,000 --\u003e 00:00:09,360\n 我要和你们谈谈我这本书里的一些东西，我希望能\n\n2\n00:00:09,360 --\u003e 00:00:13,680\n 和你们已经听到的东西产生共鸣，我会试着建立一些联系。\n```\n\n##### contentTemplateRuleMap.sourceAndTranslate\n\n保留原字幕和翻译之后的字幕，且原字幕在上面\n\n```\n1\n00:00:00,000 --\u003e 00:00:09,360\n I'm going to talk to you about some stuff that's in this book of mine that I hope will\n 我要和你们谈谈我这本书里的一些东西，我希望能\n\n2\n00:00:09,360 --\u003e 00:00:13,680\n resonate with other things that you've already heard and I'll try to make some connections\n 和你们已经听到的东西产生共鸣，我会试着建立一些联系。\n```\n\n##### contentTemplateRuleMap.translateAndSource\n\n保留原字幕和翻译之后的字幕，且翻译字幕在上面\n\n```\n1\n00:00:00,000 --\u003e 00:00:09,360\n 我要和你们谈谈我这本书里的一些东西，我希望能\n I'm going to talk to you about some stuff that's in this book of mine that I hope will\n\n2\n00:00:09,360 --\u003e 00:00:13,680\n 和你们已经听到的东西产生共鸣，我会试着建立一些联系。\n resonate with other things that you've already heard and I'll try to make some connections\n```\n\n5️⃣ 配置好该文件之后，执行 `yarn start` 或者 `npm start`, 首次执行会下载 `whisper.cpp` 和配置的对应的模型文件，会比较慢一些。下次执行将会跳过该流程\n\n如果在使用过程中遇到啥问题，可以提 Issue 或者通过 Discussions 进行讨论\n\n[![Powered by DartNode](https://dartnode.com/branding/DN-Open-Source-sm.png)](https://dartnode.com \"Powered by DartNode - Free VPS for Open Source\")\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbuxuku%2FVideoSubtitleGenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbuxuku%2FVideoSubtitleGenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbuxuku%2FVideoSubtitleGenerator/lists"}