using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; using VideoAnalysisCore.Common; using SherpaOnnx; namespace VideoAnalysisCore.AICore.SherpaOnnx { /// /// 说话人模型 /// pyannote /// public class Speaker { private static OfflineSpeakerDiarization? SD; /// /// 初始化 Speaker /// /// /// public static void Init(int speakerNumber = 0, double threshold = 0.6) { var config = new OfflineSpeakerDiarizationConfig(); //Pyannote模型地址 config.Segmentation.Pyannote.Model = Path.Combine(AppCommon.AIModelFile, "sherpa-onnx-pyannote-segmentation-3-0", "model.onnx"); //验证模型 config.Embedding.Model = Path.Combine(AppCommon.AIModelFile, "wespeaker", "wespeaker_zh_cnceleb_resnet34_LM.onnx"); //说话人数量 config.Clustering.NumClusters = speakerNumber; //说话人判定阈值 config.Clustering.Threshold = (float)threshold; SD = new OfflineSpeakerDiarization(config); } /// /// 运行 说话人日志 /// /// public static async Task Run(string task) { var filePath = Path.Combine(task.LocalPath(), task + ".wav"); if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) throw new Exception("task 音频路径未找到"); if (SD is null) throw new Exception("Speaker 未进行初始化"); var waveReader = new WaveReader(filePath); if (SD.SampleRate != waveReader.SampleRate) throw new Exception($"预期采样率:{SD.SampleRate}. 传入: {waveReader.SampleRate}"); var segments = SD.ProcessWithCallback(waveReader.Samples, (numProcessedChunks, numTotalChunks, arg) => { var progress = (double)numProcessedChunks / numTotalChunks * 100; Console.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}=> {task} 说话人日志: {progress:F2}%"); return 1; }, nint.Zero); var res = segments.Select(s => new OfflineSpeakerRes(s)); await RedisExpand.Redis.HSetAsync(RedisExpandKey.Task(task), "Speaker", res); //加入下一队列 RedisExpand.InsertChannel(Enum.RedisChannelEnum.ChatModelAnalysis, task); } } /// /// 讲话人日志结果 /// public class OfflineSpeakerRes { /// /// 总持续时间 /// [JsonIgnore] public decimal Total => End - Start; /// /// 开始时间 /// public decimal Start { get; set; } /// /// 结束时间 /// public decimal End { get; set; } /// /// 讲话人索引 /// public int SpeakerIndex { get; set; } /// /// 讲话人日志结果 /// /// public OfflineSpeakerRes(OfflineSpeakerDiarizationSegment sds) { Start = (decimal)sds.Start; End = (decimal)sds.End; SpeakerIndex = sds.Speaker; } } }