如何用Spring Boot WebFlux实现HLS(m3u8)流与AngularJS应用的代理服务
Spring Boot WebFlux实现HLS流代理的方案指导
你的思路是完全合理的,HLS协议本身就是基于文本播放列表+分片TS文件的结构,代理层只需要做好两层转发即可:第一层是master.m3u8播放列表的代理转发,第二层是播放列表内引用的分片资源的代理转发,全程用WebFlux的流式处理完全不需要把文件完整下载到本地,内存占用极低。
核心实现逻辑
- 第一层接口:接收前端请求,代理请求dacast的master.m3u8文件,注意需要把m3u8文件内的所有分片TS文件、子播放列表的原始域名替换成你自己的代理服务域名,不然前端拿到原始地址会直接请求源站,代理就失效了
- 第二层接口:接收前端转发过来的分片/子播放列表请求,再代理请求dacast对应的资源,直接以流的形式返回给前端
具体实现代码参考
1. 配置WebClient用于远程调用
@Configuration public class WebClientConfig { @Bean public WebClient hlsProxyWebClient() { return WebClient.builder() // 按需调整内存限制,避免大分片读取报错 .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024)) .build(); } }
2. 实现代理Controller
@RestController @RequestMapping("/hls-proxy") public class HlsProxyController { private final WebClient hlsProxyWebClient; // dacast源站HLS资源前缀,按需替换成实际地址 private static final String SOURCE_HLS_PREFIX = "https://dcunilive11-lh.akamaihd.net/"; // 你的代理服务资源接口前缀 private static final String PROXY_HLS_PREFIX = "http://你的服务部署域名/hls-proxy/resource?path="; public HlsProxyController(WebClient hlsProxyWebClient) { this.hlsProxyWebClient = hlsProxyWebClient; } // 对外暴露的master.m3u8获取接口,前端直接调用该接口即可拿到可用的播放列表 @GetMapping("/master") public Mono<ResponseEntity<String>> getMasterM3u8(@RequestParam String streamId) { String sourceUrl = SOURCE_HLS_PREFIX + "i/dlive_1@" + streamId + "/master.m3u8"; return hlsProxyWebClient.get() .uri(sourceUrl) .retrieve() .bodyToMono(String.class) // 替换播放列表内所有资源路径为代理服务地址 .map(content -> content.replaceAll(SOURCE_HLS_PREFIX, PROXY_HLS_PREFIX)) .map(modifiedContent -> ResponseEntity.ok() .header("Content-Type", "application/vnd.apple.mpegurl") .body(modifiedContent)); } // 内部资源代理接口,自动转发所有分片、子播放列表请求 @GetMapping("/resource") public Mono<ResponseEntity<Flux<DataBuffer>>> getHlsResource(@RequestParam String path) { String sourceUrl = SOURCE_HLS_PREFIX + path; return hlsProxyWebClient.get() .uri(sourceUrl) .retrieve() .toEntityFlux(DataBuffer.class) .map(entity -> ResponseEntity.status(entity.getStatusCode()) .headers(entity.getHeaders()) .body(entity.getBody())); } }
注意事项
- 跨域配置:需要给
/hls-proxy/**接口配置跨域允许,避免AngularJS前端跨域拦截 - 缓存优化:可以给m3u8文件和TS分片加合适的缓存头,减少重复请求源站的开销
- 权限控制:如果需要的话可以在代理层加鉴权逻辑,只有合法的前端请求才能转发到源站,避免源站地址泄露被滥用
- 路径适配:如果源站返回的m3u8里使用的是相对路径,不需要替换域名,只需要把相对路径拼到你的代理接口地址上即可
内容的提问来源于stack exchange,提问作者A Bit of Help
相关产品推荐
相关产品推荐

