人工智能——离线情况下自动给视频添加字幕,支持中文,英文,日文等等
自动生成字幕,离线,语音模型,srt字幕自己生成
前言
最近打开百度网盘,看到播放视频有一个AI字幕功能,心情非常激动,看视频的同时可以看自动生成的字幕,防止听不清视频中人物的话语
然而不是SVIP,我试用过了之后就没有这个功能选项了
我在想,如果随便哪一个“免费”播放器,都可以一边播放视频,一边生成字幕,外文自动翻译,那不是牛哄哄?
看教程,看视频都可以方便很多,因为语音太杂了,听完后有时还要猜视频中的人物说的什么,尤其是倍速情况下,有了自动生成的字幕之后,都不再是问题
问题是如何达到这一点?当然喽,重点是免费,高效
当然,我已经实现了,Follow me!
文件都在这里,下载好文件一步步来就可以了
配置环境:
- 系统: win10
- ffmpeg:ffmpeg-5.1.2-essentials_build.zip
- python:3.8.8
- python包:vosk-0.3.45-py3-none-win_amd64.whl
- 语音模型:vosk-model-cn-0.22
流程
设想这样一个情景,向视频播放器中塞进一个语音转文字模型,当它加载视频流的时候,一边提前读取视频流,用语音模型生成字幕,一遍播放已经生成字幕的视频,不就是如此吗?
先安装相关文件
当然依旧存在的一个问题是,识别到中文,英文,日文,意大利文,俄文字幕后怎么翻译为中文的问题
作为白嫖党,我是不付费的,虽然有道,百度都提供了付费的api接口,用于对视频生成srt收费,以及提供了翻译服务
可以边生成原文语音文本,再翻译为中文文本,但是问题是他是付费的啊
但我是不可能付费的
我采取的办法是这样的
将视频丢进vosk语音识别模型生成带时间戳的字幕srt文件,然后再将这个srt备份转为纯文本的的docx文件,
(这样就得到了一个不带时间戳而只有对话的纯文本docx文件,以及一个带时间戳的外文srt视频字幕文件)
然后将这个docx文件丢进谷歌翻译中翻译为中文docx文件
然后将这个翻译过的中文docx文件对照srt中文本进行替换,就得到了带时间戳的中文srt文件
安装ffmpeg
https://ffmpeg.org/download.html
这是官网
安装就是解压而已,然后在系统变量中添加文件中的bin路径
然后cmd输入命令,查看是否已经识别
ffmpeg –version
安装python包
自己从官网下再安装 https://pypi.org/
vosk-0.3.45-py3-none-win_amd64.whl放到目录下,
pip install vosk-0.3.45-py3-none-win_amd64.whl
测试模型——对视频使用语音模型生成srt字幕,拖入视频播放器中
官网 模型文件下载地址https://alphacephei.com/vosk/models
先生成字幕文件
将想要识别语言类别的对应模型解压,想要识别中文语音就用中文模型,英文就用英文模型,日文就用日文模型等
需要注意的是先将视频文件,转成单通道wma语音文件,语音模型是对wma文件识别的,抛弃了对语音识别无用的图像信息
这里有一个自动的srt字幕生成,只需要将视频文件所在的目录设置好,就可以了,它可以为目录下所有的mp4文件生成srt字幕
from moviepy.editor import *
from moviepy.audio.fx.all import audio_left_right
from moviepy.audio.AudioClip import AudioArrayClip
import time
import subprocess
import os
import sys
from vosk import Model, KaldiRecognizer, SetLogLevel
# 解压的模型文件,英文,中文用对应model
getCn = r"D:\PGMCode\Mycode\pythonCode\goodTools\videoSrtpgm\iModel\cn\vosk-model-cn-0.22"
getCn1 = r"D:\PGMCode\Mycode\pythonCode\goodTools\videoSrtpgm\iModel\cn\vosk-model-cn-kaldi-multicn-0.15"
getJP = r"D:\PGMCode\Mycode\pythonCode\goodTools\videoSrtpgm\iModel\jp\vosk-model-ja-0.22"
getEn = r"D:\PGMCode\Mycode\pythonCode\goodTools\videoSrtpgm\iModel\en\vosk-model-en-us-0.42-gigaspeech"
def list_files(path):
fileMP4List = []
fileSRTList = []
count=1
# 遍历目录下的所有文件和子目录,并输出
for root, dirs, files in os.walk(path):
for file in files:
if file.endswith("mp4"):
fileMP4List.append([count,os.path.join(root, file)])
count=count+1
if file.endswith("srt"):
fileSRTList.append(os.path.join(root, file)[:-4])
for i in range(len(fileMP4List)):
if fileMP4List[i][1][:-4] in fileSRTList:
fileMP4List[i][1]+=" 已有srt"
return fileMP4List
def getWav(videoPath):
print("提取音频")
clip = VideoFileClip(videoPath)
audio = clip.audio
# 将音频转换为单通道
audio_array = audio.to_soundarray()
audio_left_right(audio_array)
# 获取音频剪辑的持续时间
duration = audio.duration
# 将单通道音频转换为音频剪辑对象
audio_mono = AudioArrayClip(audio_array, fps=audio.fps)
newWavePath=videoPath[:-4]+'.wav'
# 保存音频为WAV文件
audio_mono.write_audiofile(newWavePath)
print("音频生成完成,准备输出srt")
return newWavePath
def getSrt(newWavePath,modelLanguage):
print("提取srt中...")
print("开始加载识别模型")
SAMPLE_RATE = 16000
SetLogLevel(-1)
model = Model(modelLanguage)
print("模型加载完毕,开始识别...")
rec = KaldiRecognizer(model, SAMPLE_RATE)
# 修改需要识别的语音文件路径
wavPath=newWavePath
print(wavPath)
rec.SetWords(True)
result = []
with subprocess.Popen(["ffmpeg", "-loglevel", "quiet", "-i",
wavPath,
"-ar", str(SAMPLE_RATE) , "-ac", "1", "-f", "s16le", "-"],
stdout=subprocess.PIPE).stdout as stream:
word=rec.SrtResult(stream)
result.append(word)
print("识别到字幕 {}".format(word))
# 生成srt文件
output = open(wavPath[:-4]+'.srt','w')
output.write("\n".join(result))
output.close()
print("srt输出完成")
os.remove(wavPath)
# 列出当前目录下的所有文件和子目录
filePath = r"D:\迅雷下载\新建文件夹"
allFile = list_files(filePath)
modelLanguage=getJP
for i in range(0, len(allFile)):
if "已有srt" in allFile[i][1]:
pass
else:
videoPath = allFile[i][1]
print("开始识别的文件为:"+videoPath)
# try:
getSrt(getWav(videoPath),modelLanguage)
# except:
# # print("字幕生成错误")
time.sleep(3)
print("设定目录全部字幕生成完成")
如果想要单条,可以麻烦点手动,下面这个是以前的,手动将视频转成声音文件,上面的是升级过的,自动在代码里转化了
古老的:
格式工厂
将代码中的音频文件换一下位置,模型文件换个解压好的名字,等待输出就行了
如果报错wma非pcm开头等等,请确认一下wma文件是否是单通道,测试中发现格式工厂使用高质量输出可以,保持原采样率,如果降低质量则识别失败,使用中保持原始采样率即可,单改通道
import subprocess
import os
import sys
from vosk import Model, KaldiRecognizer, SetLogLevel
SAMPLE_RATE = 16000
SetLogLevel(-1)
# 解压的模型文件,英文,中文用对应model
model = Model(r"C:\Users\Administrator\MyFileLi\AIPrograms\model_cn")
rec = KaldiRecognizer(model, SAMPLE_RATE)
# 修改需要识别的语音文件路径
wavPath=r"D:\FFOutput\课时1.wma"
rec.SetWords(True)
result = []
with subprocess.Popen(["ffmpeg", "-loglevel", "quiet", "-i",
wavPath,
"-ar", str(SAMPLE_RATE) , "-ac", "1", "-f", "s16le", "-"],
stdout=subprocess.PIPE).stdout as stream:
result.append(rec.SrtResult(stream))
print(result)
# 生成srt文件
output = open(wavPath.split("\\")[-1].split(".")[:-1][0]+'.srt','w')
output.write("\n".join(result))
output.close()
将srt拖入视频,输出
更多推荐
所有评论(0)