[!IMPORTANT] 🧨 💥 🎉 本项目是一个命令行工具,但非常荣幸得到了很多朋友的支持,也给我了很大的鼓舞,因此,我基于它制作了一款客户端工具,让大家能够更加方便地使用,也方便一部分不熟悉代码配置的朋友也能使用该工具。
欢迎大家移步 video-subtitle-master 以获得更加便捷的使用体验
做这个小工具的初衷:
自己有一大批外文视频,没有字幕,希望能够添加字幕文件,同时也能够将字幕文件翻译成中文, 同时希望能够通过批量处理的方式来减轻工作量。
类似需求,有一批厂商已经提供到了支持,比如 讯飞听见, 网易见外 等,但这些在线服务都涉及到视频的上传动作,效率相对比较低下。
希望能够找一个客户端工具,在本地来生成,试用了一些工具,依然不理想
最后想了一下,本地语音转文字,通常的做法就是使用目前最强的 whisper 模型来生成。那我的需求就比较简单了:
基于以上简单的思路和流程,就可以简单写一个小工具来批量处理本地的视频了。
whisper.cpp
, 它对 apple silicon 进行了优化,有较快的生成速度fluent-ffmpeg
, 无须安装 ffmpeg
tiny.en
tiny
base.en
base
small.en
small
medium.en
medium
large-v1
large-v2
large-v3
本项目的翻译能力是基于 百度/火山/deeplx 的翻译API来实现的,这些 API 的使用需要申请对的 KEY 和 SECRET, 因此,如果你需要使用到翻译服务,需要先申请一个 API 。
具体的申请方法,可以参考 https://bobtranslate.com/service/ , 感谢 Bob 这款优秀的软件。
1️⃣ 克隆本项目在本地
git clone https://github.com/buxuku/VideoSubtitleGenerator.git
2️⃣ 在项目中执行 yarn install
或者 npm install
cd VideoSubtitleGenerator
yarn install
3️⃣ 如果需要翻译,复制 .env.local
为 .env
在项目根目录,访文件用于配置翻译相关的 KEY 和 SECRET, 例如
BAIDU_
开头的为百度翻译的配置
VOLC_
开头的为火山翻译的配置
OLLAMA_
开头的为 ollama 翻译的配置
BAIDU_KEY=2023120600190xxxx
BAIDU_SECRET=PIbyKjEr1y8u18RZxxxx
VOLC_KEY=AKLTMDUwZjY4MTZkNTFmN4M3ZjlkMzlmYzAzMTdlMDExxxx
VOLC_SECRET=T0dRMllUUmpPREUzWWpjNE5HVm2Zamt4TlRObU9EUm1ORFk0T1dGbExxxx==
OLLAMA_API_URL=http://localhost:11434
OLLAMA_MODEL_NAME=llama3
OLLAMA_PROMPT=Please translate the following content from ${sourceLanguage} to ${targetLanguage}, only return the translation result can be. \n ${content}
4️⃣ 其余的配置在 config.js
文件中进行配置,每条配置均的详细的注释
// 视频文件所在目录 如 /Users/demo/video
export const videoDir = './examples';
/*
whisper.cpp 模型 支持以下
tiny.en
tiny
base.en
base
small.en
small
medium.en
medium
large-v1
large-v2
large-v3
*/
export const whisperModel = 'base.en';
// 翻译配置,视频原语言与翻译后的目标语言
export const translateConfig = {
sourceLanguage: 'en',
targetLanguage: 'zh',
};
// 支持的翻译服务商
export const supportedService = {
baidu: Symbol.for('baidu'),
volc: Symbol.for('volc'),
deeplx: Symbol.for('deeplx'),
ollama: Symbol.for('ollama'),
};
// 当前使用的翻译服务商,如果不配置,则不执行翻译流程
export const translateServiceProvider = supportedService.volc;
// 翻译结果字幕文件内容配置
export const contentTemplateRuleMap = {
onlyTranslate: Symbol.for('onlyTranslate'), // 只输出翻译内容
sourceAndTranslate: Symbol.for('sourceAndTranslate'), // 输出原始字幕和翻译字幕, 原始字幕在上面
translateAndSource: Symbol.for('translateAndSource'), // 输出翻译后的字幕和原始字幕, 翻译字幕在上面
};
// 字幕文件内容模板 支持 ${sourceContent}, ${targetContent} 变量
export const contentTemplate = {
[contentTemplateRuleMap.onlyTranslate]: '${targetContent}\n\n',
[contentTemplateRuleMap.sourceAndTranslate]: '${sourceContent}\n${targetContent}\n\n',
[contentTemplateRuleMap.translateAndSource]: '${targetContent}\n${sourceContent}\n\n',
};
// 翻译内容输出模板规则,默认只输出翻译内容, 支持 contentTemplateRuleMap 内的规则
export const contentTemplateRule = contentTemplateRuleMap.onlyTranslate;
// 原始字幕文件保存命名规则 支持 fileName, sourceLanguage, targetLanguage 变量
// 如果为空,将不保存原始字幕文件
// eg: '${fileName}.${sourceLanguage}' -> 对于视频名为 text.mp4 的英文视频原始字幕文件名为 text.en.srt
export const sourceSrtSaveName = '${fileName}.${sourceLanguage}';
// 翻译后的字幕文件保存命名规则 支持 fileName, sourceLanguage, targetLanguage 变量
export const targetSrtSaveName = '${fileName}.${targetLanguage}';
这里面的字幕内容和字幕文件名可以自定义配置,同时会将里面的 ${xxx}
变量转为对应的字符
核心配置主要为以下几项
// 当前使用的翻译服务商,如果不配置,则不执行翻译流程
export const translateServiceProvider = supportedService.volc;
支持
// 翻译内容输出模板规则,默认只输出翻译内容, 支持 contentTemplateRuleMap 内的规则
export const contentTemplateRule = contentTemplateRuleMap.onlyTranslate;
支持以下几种设置模式
只保留翻译后的结果内容,如
1
00:00:00,000 --> 00:00:09,360
我要和你们谈谈我这本书里的一些东西,我希望能
2
00:00:09,360 --> 00:00:13,680
和你们已经听到的东西产生共鸣,我会试着建立一些联系。
保留原字幕和翻译之后的字幕,且原字幕在上面
1
00:00:00,000 --> 00:00:09,360
I'm going to talk to you about some stuff that's in this book of mine that I hope will
我要和你们谈谈我这本书里的一些东西,我希望能
2
00:00:09,360 --> 00:00:13,680
resonate with other things that you've already heard and I'll try to make some connections
和你们已经听到的东西产生共鸣,我会试着建立一些联系。
保留原字幕和翻译之后的字幕,且翻译字幕在上面
1
00:00:00,000 --> 00:00:09,360
我要和你们谈谈我这本书里的一些东西,我希望能
I'm going to talk to you about some stuff that's in this book of mine that I hope will
2
00:00:09,360 --> 00:00:13,680
和你们已经听到的东西产生共鸣,我会试着建立一些联系。
resonate with other things that you've already heard and I'll try to make some connections
5️⃣ 配置好该文件之后,执行 yarn start
或者 npm start
, 首次执行会下载 whisper.cpp
和配置的对应的模型文件,会比较慢一些。下次执行将会跳过该流程
如果在使用过程中遇到啥问题,可以提 Issue 或者通过 Discussions 进行讨论