如何在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
相关产品推荐
相关产品推荐

