Html5 的 <video />
只能在整个视频文件加载完成后才能播放,体验极其不好。如果仅是支持基于 Http(s) 的流媒体播放的话,可以直接利用 Http 协议的 Content-Range 头。
所以本文的核心思想是使 Sanic 后端能正确处理 Videojs 发送的 byte-range 请求,并回以带 Content-Range 的文件流响应即可。
安装 Video.js
在 React 项目目录下安装 Video.js 及其主题 UI 库。
1 2 3
| npm install video.js
npm install video.js @videojs/themes
|
React 组件中使用 Video.js
App.js 中,创建 video 对象并将其与 Video.js player 关联:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import './App.css'; import React from 'react'; import videojs from 'video.js'; import "video.js/dist/video-js.css"; import '@videojs/themes/dist/sea/index.css';
export default class App extends React.Component {
componentDidMount() { this.player = videojs(this.videoNode, this.props, function onPlayerReady() { console.log('onPlayerReady', this) }); }
render() { return ( <div> <div data-vjs-player> <video ref={node => this.videoNode = node} className="video-js vjs-theme-sea"></video> </div> </div> ) } }
|
index.js 中,通过 /api/video
接口向后端发送视频请求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App';
const videoJsOptions = { autoplay: false, controls: true, sources: [{ src: '/api/video', type: 'video/mp4' }] }
ReactDOM.render( <React.StrictMode> <App {...videoJsOptions}/> </React.StrictMode>, document.getElementById('root') );
|
Sanic 中处理请求
Sanic 提供文件流响应对象,并提供 api 处理请求中的 byte-range。将两者结合,即可构造出一个带 Content-Range 头的响应。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from sanic import Sanic from sanic.response import file_stream from sanic.handlers import ContentRangeHandler from sanic.compat import stat_async
app = Sanic('player')
app.static('/static', './static')
@app.get('/api/video') async def api(request): file_path = './1.mp4' stats = await stat_async(file_path) _range = ContentRangeHandler(request, stats) return await file_stream(file_path, _range=_range)
|
结论
基本能达到“秒开”效果。
需要媒体格式支持才行。比如 MP4,就需要在其文件开头具有 moov atom 信息。
参考
Problems with playback:https://docs.videojs.com/tutorial-troubleshooting.html#problems-with-playback
Problems when hosting media:https://docs.videojs.com/tutorial-troubleshooting.html#problems-when-hosting-media
Video.js and ReactJS integration:https://docs.videojs.com/tutorial-react.html#react-class-component-example
ContentRangeHandler:https://sanic.readthedocs.io/en/stable/sanic/api/core.html#sanic.handlers.ContentRangeHandler
如何优雅地实现网页播放视频:https://www.jianshu.com/p/65af0f01cb97