yolo8+声纹识别(实时字幕)

发布于:2025-07-16 ⋅ 阅读:(23) ⋅ 点赞:(0)

现在已经完成了人脸识别跟踪 ✅,接下来要:

✅ 加入「声纹识别(说话人识别)」功能,识别谁在讲话,并在视频中“这个人”的名字旁边加上「正在讲话」。

这属于多模态识别(视觉 + 音频):

  1. 说明实现原理与推荐工具

  2. 给出整体流程架构

  3. 推荐稳定的开源工具包

  4. 展示如何与当前人脸识别结合


✅ 整体目标

希望实现:

  • 摄像头中显示所有人的名字(已完成)

  • 通过麦克风监听讲话内容

  • 根据声纹判断当前是谁在讲话

  • 在视频中对这个人显示“正在讲话”

✅ 实现路径(视觉 + 音频)

🔊 声纹识别部分(说话人识别)

目标 技术名称 推荐工具
声音中识别是谁 说话人识别(Speaker Identification) pyannote-audio不推荐, resemblyzer推荐
声音中找谁在说话 说话人活动检测(Voice Activity Detection, VAD) webrtcvad, silero-vad
声纹注册(采集说话人音频) Speaker Embedding resemblyzer, speechbrain

1. pyannote-audio和resemblyzer区别核心功能对比

特性 pyannote-audio resemblyzer
主要用途 说话人分割(Diarization)、语音活动检测(VAD)、重叠语音检测 声纹嵌入(Speaker Embedding)、实时声纹比对
模型复杂度 高(多模块联合优化,端到端流程) 低(轻量级,专注声纹向量提取)
预训练模型 提供完整的说话人分割管道(如 speaker-diarization-3.1 仅提供声纹编码器(如 VoiceEncoder
实时性 较慢(适合离线处理) 快(支持实时流式处理)
依赖项 依赖 PyTorch 和 Hugging Face 模型库 仅需 NumPy 和 PyTorch
典型应用场景 会议记录、广播分析、多说话人数据集标注 实时声纹验证、说话人聚类

2. 技术实现差异

pyannote-audio
  • 模块化设计
    包含独立的子模块(如 segmentationembeddingclustering),可灵活组合或替换16。

  • 端到端流程
    支持从语音活动检测到说话人聚类的完整流程,适合复杂场景(如重叠语音处理)6。

  • 性能优化
    部分版本(如 speaker-diarization-3.1)处理长音频较慢,推荐使用 v2 版本加速12。

resemblyzer
  • 轻量级
    仅实现声纹向量提取(512 维嵌入),需自行结合聚类算法(如 K-Means)完成分割5。

  • 实时性
    适合流式处理,单次推理速度快(约 0.1 秒/语音片段)5。

  • 易用性
    无需复杂配置,适合快速验证声纹相似度

✅ 推荐方案(轻量 + 可行)

🔧 声纹识别用 resemblyzer,搭配 YOLO 人脸

注意!!!!!!!!!!!!

先安装ffmpeg,resemblyzer会依赖

1. 为什么 resemblyzer 需要 ffmpeg

resemblyzer 的核心功能是处理音频文件(如 MP3、WAV 等),但它本身 不直接调用 ffmpeg,而是通过以下依赖链间接使用:

resemblyzer 
→ librosa(音频加载) 
→ audioread(解码非WAV格式) 
→ ffmpeg(实际解码工具)
  • 关键点
    只有处理 非WAV格式(如MP3、MP4) 时才需要 ffmpeg。如果仅使用 WAV 文件,可跳过安装。

✅ 安装【ffmpeg】

https://ffmpeg.org/打开网站下载自己的版本

接下来📦 安装其他依赖:

pip install resemblyzer sounddevice webrtcvad numpy 

💡 resemblyzer 是 Facebook 开源的轻量级声纹识别库,能实时从麦克风提取声纹并判断是否是目标用户。

✅ 总体流程图(视觉 + 音频结合):


✅ 示例代码框架(概要)

1、查看在PyCharm里面能不能使用ffmpeg

import subprocess

try:
    result = subprocess.run(["ffmpeg", "-version"], capture_output=True, text=True)
    if result.returncode == 0:
        print("✅ ffmpeg 已安装")
    else:
        print("❌ ffmpeg 未安装或异常")
except FileNotFoundError:
    print("❌ 未找到 ffmpeg 命令")

2、拿两段音频识别


from resemblyzer import VoiceEncoder, preprocess_wav
import numpy as np

# 初始化编码器
encoder = VoiceEncoder()

# 加载并预处理音频
wav1 = preprocess_wav("/Users/lianying/Desktop/yolo/1.m4a")  # 支持 .wav/.mp4 文件
wav2 = preprocess_wav("/Users/lianying/Desktop/yolo/2.m4a")

# 提取声纹嵌入(512 维向量)
embed1 = encoder.embed_utterance(wav1)
embed2 = encoder.embed_utterance(wav2)

# 计算相似度(余弦相似度)
similarity = np.dot(embed1, embed2)
print(f"声纹相似度: {similarity:.4f}")  # 0.0~1.0,>0.8 可视为同一人

已经成功识别声纹了 !!!!!!!

✅ 接下来整合以下功能:

模块 状态
🧠 人脸识别 + 声纹识别 ✅ 已完成(已有)
🎙️ Whisper 语音识别 ✅ 可用(ffmpeg 已安装)
💬 实时字幕显示 🔜 马上整合

已经安装好了 ffmpeg ✅,那现在可以 正式接入 Whisper 实现“说话内容转字幕”

🧠 模型大小选择:使用 Whisper 的哪个版本?(默认推荐 base

  • tiny(最快) / base(准确+轻)/ small(较高准确)

✅ 安装 Whisper(OpenAI 官方)

pip install -U openai-whisper

✅ Whisper 使用示例(语音转文字)

import whisper
model = whisper.load_model("base")  # 也可以用 "tiny", "small", "medium", "large"

# 录音 → 保存为 temp.wav
import sounddevice as sd
from scipy.io.wavfile import write

fs = 16000
duration = 3
audio = sd.rec(int(duration * fs), samplerate=fs, channels=1)
sd.wait()
write("temp.wav", fs, audio)

# 语音识别
result = model.transcribe("temp.wav", language="zh")
print("识别内容:", result["text"])

🎯 目标

基于摄像头视频流,识别谁在讲话,并把“张三(正在讲话):你好啊,我是张三”样式的字幕实时显示在画面上(支持中文)

✅ 内容包含:

模块 技术 状态
人脸识别 YOLOv8 + face_recognition
声纹识别 Resemblyzer
语音转文字 Whisper(base)
实时录音 sounddevice
字幕显示 PIL + 中文字体支持

✅ 使用前请确认:

如下文件夹结构:

import os
import cv2
import numpy as np
from PIL import ImageFont, ImageDraw, Image
import face_recognition
from resemblyzer import VoiceEncoder, preprocess_wav
import sounddevice as sd
from scipy.io.wavfile import write
import whisper
from ultralytics import YOLO

# === 参数设置 ===
VOICE_DB = "voice_db"
FACES_DB = "faces"
FONT_PATH = "font/AlimamaDaoLiTi-Regular.ttf"  # 中文黑体字体路径(请确保该字体文件存在)
SAMPLE_RATE = 16000
RECORD_DURATION = 1  # 录音时间(秒)
CONFIDENCE_THRESHOLD = 0.75

# === 初始化模型 ===
print("加载 YOLOv8 模型...")
yolo_model = YOLO("/Users/lianying/Desktop/yolo/model_face.pt")  # 检测人脸用
print("加载人脸识别数据库...")
known_encodings, known_names = [], []
for name in os.listdir(FACES_DB):
    for img_file in os.listdir(os.path.join(FACES_DB, name)):
        img_path = os.path.join(FACES_DB, name, img_file)
        img = face_recognition.load_image_file(img_path)
        enc = face_recognition.face_encodings(img)
        if enc:
            known_encodings.append(enc[0])
            known_names.append(name)

print("加载声纹识别数据库...")
encoder = VoiceEncoder()
speaker_embeddings = {}
for file in os.listdir(VOICE_DB):
    if file.endswith(".wav"):
        name = file.split(".")[0]
        wav = preprocess_wav(os.path.join(VOICE_DB, file))
        embed = encoder.embed_utterance(wav)
        speaker_embeddings[name] = embed

print("加载 Whisper 模型...")
asr_model = whisper.load_model("base")

# === 字体 ===
font = ImageFont.truetype(FONT_PATH, 24)

# === 摄像头 ===
cap = cv2.VideoCapture(0)
frame_count = 0
interval = int(30 * RECORD_DURATION)  # 每 interval 帧识别一次
current_speaker = ""
current_text = ""

while True:
    ret, frame = cap.read()
    if not ret:
        break

    frame_count += 1

    # 每 interval 帧录音 + 声纹识别 + Whisper
    if frame_count % interval == 0:
        print("\n[INFO] 正在录音并分析说话人...")
        audio = sd.rec(int(RECORD_DURATION * SAMPLE_RATE), samplerate=SAMPLE_RATE, channels=1)
        sd.wait()
        write("temp.wav", SAMPLE_RATE, audio)

        # 声纹识别
        wav = preprocess_wav("temp.wav")
        embed = encoder.embed_utterance(wav)
        best_name, best_score = "", 0.5
        for name, ref in speaker_embeddings.items():
            sim = np.dot(embed, ref)
            if sim > best_score:
                best_score = sim
                best_name = name
        current_speaker = best_name if best_score > CONFIDENCE_THRESHOLD else ""

        # Whisper 语音识别
        result = asr_model.transcribe("temp.wav", language="zh")
        current_text = result["text"].strip()
        print(f"[识别] {current_speaker}:{current_text}")

    # 人脸检测 + 标注
    results = yolo_model.predict(frame, classes=[0], conf=0.4, verbose=False)
    for result in results:
        boxes = result.boxes.xyxy.cpu().numpy().astype(int)
        for box in boxes:
            x1, y1, x2, y2 = box
            face_crop = frame[y1:y2, x1:x2]
            rgb_crop = cv2.cvtColor(face_crop, cv2.COLOR_BGR2RGB)
            encs = face_recognition.face_encodings(rgb_crop)
            name = "未知"
            if encs:
                matches = face_recognition.compare_faces(known_encodings, encs[0])
                face_distances = face_recognition.face_distance(known_encodings, encs[0])
                if True in matches:
                    best_match = np.argmin(face_distances)
                    name = known_names[best_match]

            # 准备显示信息
            label = name
            if name == current_speaker:
                label += "(正在讲话)"
                if current_text:
                    label += f":{current_text}"

            # 绘图(PIL 支持中文)
            pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
            draw = ImageDraw.Draw(pil_img)
            draw.rectangle([x1, y1, x2, y2], outline="green", width=2)
            draw.text((x1, y1 - 30), label, font=font, fill=(255, 0, 0))
            frame = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)

    cv2.imshow("实时人脸 + 声纹 + 字幕识别", frame)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()


网站公告

今日签到

点亮在社区的每一天
去签到