⚡️ perf(media): 音频代理改为流式转发

- downloadMedia 拿到响应头即返回 Body,音频不再全量驻留内存,改由 io.Copy 流式写出
- 重试仅覆盖响应阶段;Body 读取中途失败由客户端自行重试
- 请求头设置提取为 setMediaHeaders 复用;data_uri 模式保持全量读取(本就需驻留内存)
- 漫画代理因需解密后输出,维持原有全量方式
This commit is contained in:
chenxin committed 2026-09-30 00:25:09 +08:00
1 parent f89bee8ddc
commit ad6d28fd85
3 files changed
+54 -47

No files matched your search

+8 -7
View File
@@ -4,15 +4,16 @@ import (
"database/sql"
"encoding/json"
"fmt"
"io"
"time"
)
// AudioCacheItem 音频缓存项
type AudioCacheItem struct {
OriginalURL string `json:"original_url"` // 原始CDN URL
DeviceID string `json:"device_id"` // 关联的设备ID
DeviceID string `json:"device_id"` // 关联的设备ID
Headers map[string]string `json:"headers"` // 请求头信息
CachedAt time.Time `json:"cached_at"` // 缓存时间
CachedAt time.Time `json:"cached_at"` // 缓存时间
}
// GenerateAudioProxyURL 生成音频代理URL
@@ -49,8 +50,8 @@ func GenerateAudioProxyURL(originalURL, deviceID string, headers map[string]stri
return fmt.Sprintf("/audio/proxy/%s", key)
}
// HandleAudioProxy 处理音频代理请求
func HandleAudioProxy(key string) ([]byte, string, error) {
// HandleAudioProxy 处理音频代理请求(流式返回,调用方负责 Close)
func HandleAudioProxy(key string) (io.ReadCloser, string, error) {
var originalURL, deviceID string
var headers map[string]string
@@ -95,13 +96,13 @@ func HandleAudioProxy(key string) ([]byte, string, error) {
headers = make(map[string]string)
}
// 下载音频内容,使用关联的设备信息
data, contentType, err := downloadMediaWithRetry(originalURL, deviceID, headers, 3)
// 下载音频内容(流式),使用关联的设备信息
body, contentType, err := downloadMediaWithRetry(originalURL, deviceID, headers, 3)
if err != nil {
return nil, "", fmt.Errorf("下载音频失败: %w", err)
}
return data, contentType, nil
return body, contentType, nil
}
// CleanExpiredAudioCache 清理过期的音频缓存