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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 08:45:04