调用硅基流动语音转文字接口
  1. 目前有 2 个模型是免费的, TeleAI/TeleSpeechASR 与 FunAudioLLM/SenseVoiceSmall

  2. 注意 httpclient 时要重置一下策略, 见 asp.net core 转发客户端 ai 调用 中的 ClearResilienceHandlers 的使用

调用接口

 public async Task<IResult> AudioTranscriptionAsync(HttpContext context)
    {
        var host = options.Value.Host;
        var apiKey = options.Value.ApiKey;

        if (string.IsNullOrWhiteSpace(host) || string.IsNullOrWhiteSpace(apiKey))
        {
            throw new ArgumentException("未定义 ai host 或 apkey");
        }

        // 音频处理通常较慢,保持较长的超时时间
        using var ts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
        var cancellationToken = ts.Token;

        try
        {
            // 拼接 SiliconFlow 的音频转文字地址
            var uri = new Uri(new Uri(host), "audio/transcriptions");

            // 1. 获取客户端上传的 Form 数据
            // 注意:Avalonia 端上传时,确保字段名为 "file" 和 "model"
            var form = await context.Request.ReadFormAsync(cancellationToken);
            var file = form.Files.GetFile("file");
            // var model = form["model"].ToString() ?? "TeleAI/TeleSpeechASR";
            var model = form["model"].ToString() ?? "FunAudioLLM/SenseVoiceSmall";

            if (file == null)
            {
                return Results.BadRequest("未检测到音频文件");
            }

            // 2. 构建转发给 SiliconFlow 的 Multipart 请求
            using var requestContent = new MultipartFormDataContent();

            // 写入模型名称
            requestContent.Add(new StringContent(model), "model");

            // 写入文件流
            await using var fileStream = file.OpenReadStream();
            var streamContent = new StreamContent(fileStream);
            streamContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType ?? "audio/mpeg");
            requestContent.Add(streamContent, "file", file.FileName);

            // 3. 准备发送请求
            var requestMessage = new HttpRequestMessage(HttpMethod.Post, uri)
            {
                Content = requestContent,
            };
            requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);

            // 4. 发送请求
            var response = await httpClient.SendAsync(requestMessage, cancellationToken);

            // 5. 将结果返回给 Avalonia 客户端
            var resultJson = await response.Content.ReadAsStringAsync(cancellationToken);

            // 保持与下游一致的状态码
            return Results.Content(resultJson, "application/json", Encoding.UTF8, (int)response.StatusCode);
        }
        catch (Exception exception)
        {
            logger.LogError(exception, "处理音频转文字请求失败");
            return Results.Problem("Internal Server Error");
        }
    }

生成测试语音文件

在 macos 下调用


say -v "Tingting" --progress -r 220 "这是一段由系统自动生成的测试语音,用于验证硅基流动的接口。" -o temp.aiff && ffmpeg -i temp.aiff -ar 16000 -ab 32k -y test_audio.mp3 && rm temp.aiff && afplay test_audio.mp3

-v 角色,使用 say -v ? 列出所有支持的角色
--progress 显示转换的进度
-i 在播放语音的时候高亮对应的文字,该参数不支持输出文件
-r 语速,默认 180/分钟
-o 输出
ffmpeg 将生成文件转为 mp3
afplay 播放生成的 mp3

.http 测试


# 使用 < 载入处理语音 mp3 文件
POST {{apihost}}/api/ai/v1/audio/transcriptions
Authorization: Bearer xxxx
Content-Type: multipart/form-data; boundary=WebAppBoundary

--WebAppBoundary
Content-Disposition: form-data; name="model"

FunAudioLLM/SenseVoiceSmall
--WebAppBoundary
Content-Disposition: form-data; name="file"; filename="test_audio.mp3"
Content-Type: audio/mpeg

< /Users/iox/Desktop/test_audio.mp3
--WebAppBoundary--
上一篇