1.问题描述
我用flask框架简单搭建一个网站,借用到别的网站的一些视频资源,是m3u8这种串流视频格式,发现了这种跨域请求问题。如果是直接访问这种 m3u8链接,chrome浏览器会把index.m3u8
文件下载下来,可以使用Native HLS Playback
插件实现直接播放,而不是下载。而在手机上一些浏览器是可以支持访问这种m3u8链接并且直接播放的,并且这种是没有跨域问题的。而跨域问题的出现一般是这样:
```html
<meta>
```
这种网页直接本地打开或者建立成服务然后去访问对应网页,都会出现跨域问题(如果对方服务器加入了跨域监测)。而我要搭建的一个网站是需要构建一个类似这种的网页(我不想直接跳转到m3u8链接实现播放)。
2. 解决办法
因为我用flask框架 构建了一个web 服务端,所以我建立一个请求接口,这个接口 作用就是请求对方的 m3u8 链接,然后将响应内容返回给用户:
python @app.route('/<int:videoId>.m3u8') def video(videoId): url = f"https://xxxx/{videoId}.m3u8" result = requests.get(url).text return result, 200, [("content-type","application/vnd.apple.mpegurl"),("access-control-allow-methods","GET"),("access-control-allow-methods","POST, GET, DELETE, OPTIONS"),("access-control-allow-origin","*")]
这样做就可以实现解决跨域问题,并且在我直接写的html网页中引入我本地服务的这个链接也不会有跨域问题,但是使用这种方法有一个前提,就是你请求的m3u8这个文件内容中的ts链接是必须带有完整地址的,而不是采用相对地址,如果采用相对地址,那么播放是请求的ts文件就是相对你自己构建的服务端,而不会请求到对方服务器上的内容。采用相对地址这种问题也很容易解决,可以在这个函数中实现 主域名拼接,然后将其返回。
并且在这个函数中可以实现很多突破防盗链的功能,例如 检测请求头中的 referer
字段。可以这样写:
```python
@app.route('/
.m3u8') def video(videoId): url = f"https://xxxxx/{videoId}.m3u8"
result = requests.get(url,headers={"referer":"https://xxxxxx"}).text return result, 200, [("content-type","application/vnd.apple.mpegurl"),("access-control-allow-methods","GET"),("access-control-allow-methods","POST, GET, DELETE, OPTIONS"),("access-control-allow-origin","*")] ```
3. 另一种解决办法
浏览器中支持很多协议,我相信都见到过这种:
二进制图片经过base64编码的,但是这个东西叫data协议,是浏览器支持协议的一种。浏览器使用这种协议作用一般用于图片数据的加密,js请求过来二进制数据,然后经过js算法解密回来,然后在浏览器中显示出来(一般都是AES加密),是一种图片防盗链的技术。
二进制都可以用data协议表示出来,那么m3u8文本文件的内容也是可以用这种协议表示出来。
html <source id="source" src="data:application/vnd.apple.mpegurl;base64,I0VYVE0z.....经过base64编码的m3u8数据" type="application/x-mpegURL">
当然这种还是和上面一样,需要ts链接是绝对路径,如果不是绝对路径需拼接主域名后进行base64编码。使用这种方式的 html 文件就可以完全的脱离本地建立的服务端了,因为所有数据都在这个html文件中(当然不是ts视频数据,是ts完整链接)。
这种方法也可以解决跨域问题。