You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Unity C#中接收FastAPI返回的StreamingResponse?

如何在Unity C#中接收FastAPI的StreamingResponse流式响应

我用Python的FastAPI实现了一个返回StreamingResponse的语音识别接口,路由代码如下:

@asr_router.post("/recognition_stream")
async def api_recognition_stream(to_simple: int = Body(1, description="是否繁体转简体", embed=True),
                                 remove_pun: int = Body(0, description="是否删除标点符号", embed=True),
                                 language: str = Body("zh", description="设置语言,简写,如果不指定则自动检测语言", embed=True),
                                 task: str = Body("transcribe", description="识别任务类型,支持transcribe和translate", embed=True),
                                 audio: UploadFile = File(..., description="音频文件")):
    global model_semaphore
    print("接收到数据!开始处理...")
    if language == "None": language = None
    if model_semaphore is None:
        model_semaphore = asyncio.Semaphore(5)
    await model_semaphore.acquire()
    contents = await audio.read()
    data = BytesIO(contents)
    generator = recognition(file=data, to_simple=to_simple, remove_pun=remove_pun, language=language, task=task)
    background_tasks = BackgroundTasks()
    background_tasks.add_task(release_model_semaphore)
    print("完成数据处理!开始进行数据推送...")
    return StreamingResponse(generator, background=background_tasks)

但在Unity C#中调用该接口时,用UnityWebRequest.downloadHandler.data只能拿到第一个数据块,无法获取后续的流式数据。我的Unity请求代码如下:

WWWForm form = new WWWForm();
form.AddBinaryData("audio", audioBytes, "test.mp3", "audio/mpeg");
UnityWebRequest www = UnityWebRequest.Post(m_SpeechRecognizeURL, form);
Debug.Log("PostURL:" + m_SpeechRecognizeURL);
www.SetRequestHeader("accept", "application/json");

yield return www.SendWebRequest();
if (www.result != UnityWebRequest.Result.Success)
{
    Debug.LogError("Error sending audio file: " + www.error);
}
else
{
    byte[] _responseByte = www.downloadHandler.data;
    string responseText = Encoding.Default.GetString(_responseBytes);
    // process json received then.
    Debug.Log(responseText);
    // _callback(_response.text);
}

已通过Python Requests测试接口,确认流式响应功能正常,需要解决Unity端接收完整流式数据的问题。


解决方案:使用DownloadHandlerScript自定义处理流式数据

Unity默认的DownloadHandler会等待整个响应完成才返回数据,要实时接收流式数据,必须自定义DownloadHandlerScript来逐块处理:

1. 创建自定义流式DownloadHandler类

using UnityEngine;
using UnityEngine.Networking;
using System.Text;

public class StreamingDownloadHandler : DownloadHandlerScript
{
    private StringBuilder _fullResponse = new StringBuilder();
    // 定义数据块接收回调,用于实时处理每一段数据
    public delegate void DataChunkReceived(string chunk);
    public DataChunkReceived OnDataChunkReceived;

    public StreamingDownloadHandler() : base(new byte[4096]) { }

    // 每收到一块数据就会触发这个方法
    protected override bool ReceiveData(byte[] data, int dataLength)
    {
        if (data == null || dataLength <= 0)
        {
            Debug.LogWarning("Received empty data chunk");
            return false;
        }

        // 将字节数组转换为字符串(注意编码要和FastAPI返回一致,这里用UTF-8)
        string chunk = Encoding.UTF8.GetString(data, 0, dataLength);
        _fullResponse.Append(chunk);

        // 触发回调,传递当前数据块
        OnDataChunkReceived?.Invoke(chunk);
        return true;
    }

    // 响应全部接收完成时触发
    protected override void CompleteContent()
    {
        Debug.Log($"Streaming response finished. Full content:\n{_fullResponse.ToString()}");
    }

    // 接收响应长度(可选处理)
    protected override void ReceiveContentLength(int contentLength)
    {
        Debug.Log($"Expected total content length: {contentLength} bytes");
    }
}

2. 修改Unity请求代码,使用自定义Handler

IEnumerator SendStreamingSpeechRequest(byte[] audioBytes)
{
    WWWForm form = new WWWForm();
    form.AddBinaryData("audio", audioBytes, "test.mp3", "audio/mpeg");
    
    UnityWebRequest www = UnityWebRequest.Post(m_SpeechRecognizeURL, form);
    
    // 实例化自定义流式处理Handler
    StreamingDownloadHandler streamingHandler = new StreamingDownloadHandler();
    // 注册数据块接收回调,实时处理每一段返回数据
    streamingHandler.OnDataChunkReceived += HandleStreamingDataChunk;
    www.downloadHandler = streamingHandler;

    // 根据FastAPI返回的数据格式设置Accept头,如果是纯文本流用text/plain,JSON流用application/json
    www.SetRequestHeader("Accept", "text/plain");

    Debug.Log("Posting to URL: " + m_SpeechRecognizeURL);

    // 异步发送请求,逐帧等待进度(不要直接yield return SendWebRequest,否则会等全部响应完成)
    var requestOperation = www.SendWebRequest();
    while (!requestOperation.isDone)
    {
        yield return null;
    }

    if (www.result != UnityWebRequest.Result.Success)
    {
        Debug.LogError($"Request failed: {www.error}");
    }
    else
    {
        Debug.Log("Streaming request completed successfully");
    }

    // 清理回调,避免内存泄漏
    streamingHandler.OnDataChunkReceived -= HandleStreamingDataChunk;
}

// 实时处理每一块流式数据的方法
void HandleStreamingDataChunk(string dataChunk)
{
    Debug.Log($"Received data chunk:\n{dataChunk}");
    // 在这里添加你的业务逻辑,比如解析JSON片段、更新UI显示识别结果等
}

3. 关键注意事项

  • FastAPI的StreamingResponse默认会启用分块传输编码(Transfer-Encoding: chunked),无需额外配置,确保你的生成器是逐段输出数据的
  • 必须使用自定义DownloadHandlerScript,Unity默认的DownloadHandlerBuffer会缓存所有数据直到响应结束,无法实现流式接收
  • 编码要和FastAPI返回的一致,建议统一用UTF-8,避免乱码
  • 如果返回的是JSON片段,需要在HandleStreamingDataChunk中处理每一段JSON(比如拼接成完整JSON或单独解析片段)

内容的提问来源于stack exchange,提问作者JeffHuang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 15:10:56