微信扫码
与创始人交个朋友
我要投稿
之前做了一个 语音大模型交互的程序,开源后受到大家的喜爱,很是开心,也带了不少的公众号粉丝,没有看过的可以去看看llm+funasr+tts,diy大模型语音助手,一个自己控制的siri,保姆教程,这几天看openai演示的和GPT-4o的视频交互,挺好玩的,有点类似谷歌眼镜了,可以时时聊天,本着抛砖引玉的思想,我也搞了一个低配版玩玩,测试后觉得还挺有意思,这里开源给大家,大家可以测试一下,优化一下,也可以使用本地模型替换一下,哈哈,还不多先看效果
屌丝作者也出镜了,哈哈
下边来讲解一下,具体实现
项目技术总揽
本项目的三大核心技术是:视频抽帧,语音转文本,语言大模型根据问题和图片流产生答案,文本合成语音。三大技术中都可以使用开源项目,但是作者测试,开源的多模态效果缺确实有限(比如:llava:13b)所以大模型最终选择了gpt-4o(我会推荐一个国内可用的gpt-4o,大家想试试的可以试试,此处没有赞助费^_^),.语音转文字是用的funasr阿里开源的;文本合成语音有很多可选方案,比如chattts,fishspeeh,edge-tts,本次基于时间和效果的考虑,选择了edgetts,速度快,效果好,声音可选
技术代码简介
1、语音转文本funasr
model = AutoModel(model="paraformer-zh", vad_model="fsmn-vad", punc_model="ct-punc")def get_spk_txt(file):res = model.generate(input=file, batch_size_s=300, hotword='魔搭')return res[0]["text"]
这里使用paraformer-zh 模型,第一使用会下载模型,可能会慢一点,这个函数可以直接将语音文件转成文本,当然还有许多其他模型大家可以去官网看看
2、视频抽帧,
def extract_frames(video_path, output_dir, frame_rate=1):
"""
从视频中抽取帧并保存到指定目录
参数:
video_path (str): 视频文件的路径
output_dir (str): 保存抽取帧的目录
frame_rate (int): 每秒抽取的帧数,默认为1帧每秒
返回:
int: 抽取的帧数
"""
# 如果输出目录不存在,则创建
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 打开视频文件
cap = cv2.VideoCapture(video_path)
# 获取视频的帧率
video_fps = cap.get(cv2.CAP_PROP_FPS)
# 计算每隔多少帧抽取一次
frame_interval = int(video_fps / frame_rate)
frame_count = 0
saved_frame_count = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 如果当前帧是需要保存的帧
if frame_count % frame_interval == 0:
frame_filename = os.path.join(output_dir, f"frame_{saved_frame_count:04d}.jpg")
cv2.imwrite(frame_filename, frame)
saved_frame_count += 1
frame_count += 1
# 释放视频捕获对象
cap.release()
return saved_frame_count
3、调用gpt-4o做视频流识别同时给出语音需求的文本输入
def get_result(spk_content,images):
# 中文 Prompt 指令
prompt = (
"你好,图中"+spk_content
)
base64_images = [encode_image(image) for image in images]
# 组织用户消息
user_content = [{"type": "text", "text": prompt}]
base64_images = [
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{base64_image}",
"detail": "high",
},
}
for base64_image in base64_images
]
user_content.extend(base64_images)
messages_template = [{"role": "user", "content": user_content}]
# 构造请求参数
# OpenAI API Key
response = openai.ChatCompletion.create(
model="gpt-4o",
messages=messages_template,
n=1,
max_tokens=1024,
temperature=0,
seed=42,
)
# print(response.json())
result = response.choices[0].message.content
return result
函数的输入是,用户视频中说的话转的文本,和视频抽帧后的图片流
4、语音合成,使用edge-tts
async def get_voice(text):"""Main function"""VOICE = "zh-CN-XiaoxiaoNeural"output_file = "response"+str(time())+".mp3"communicate = edge_tts.Communicate(text, VOICE)await communicate.save(output_file)return output_file
上篇文章说过,这个可以选择很多语音,大家可以去参考llm+funasr+tts,diy大模型语音助手,一个自己控制的siri,保姆教程
5、调用视频抽帧、语音转文本、gpt-4o,语音合成
def save_video(video):
# 获取当前时间戳
timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
# 生成保存文件的路径
video_path = os.path.join(SAVE_DIR, f"video_{timestamp}.mp4")
# 将视频保存到文件
with open(video, "rb") as f:
video_data = f.read()
with open(video_path, "wb") as f:
f.write(video_data)
file_name = str(time())
output_dir = "pic/"+file_name# 替换为你希望保存帧的目录
frame_rate = 3# 每秒抽取1帧
num_frames = extract_frames(video_path, output_dir, frame_rate)
print(f"总共抽取了 {num_frames} 帧")
spk_content = get_spk_txt(video_path)
print("我的语音:",spk_content)
images = [output_dir+"/"+i for i in os.listdir(output_dir)]
resp = get_result(spk_content,images)
# 生成语音文件
# audio_file = get_voice(resp)
audio_file = asyncio.run(get_voice(resp))
print("语音合成完成")
return resp, os.path.join(os.getcwd(), audio_file) if audio_file else None
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-05-30
2024-09-12
2024-06-17
2024-08-06
2024-08-30
2024-04-21
2024-06-26
2024-07-07
2024-06-14
2024-07-21
2024-09-26
2024-09-26
2024-09-01
2024-07-15
2024-07-14
2024-07-10
2024-07-02
2024-06-29