在TypeScript中使用video.js

目的


(客户、甲方爸爸、......)要在网页中播放视频。

视频文件后台同事已经分片处理好了,生成了m3u8文件,同时分片前的原始视频(mp4文件)也在服务器上保留了一份。

理论部分


✨ 为什么使用video.js

首先,video.js使用得非常广泛,这就有了扎实的群众基础‍‍‍,由此衍生的是文档和实例也多啊,那学习(其实就是抄)起来甚是方便。

其次,因为要播放m3u8文件,但PC端浏览器并不支持video标签直接播放m3u8格式的视频,video.js安装了videojs-contrib-hls.js插件后就可以播放了,而且7以后的版本已经支持这类文件了,不用再装此插件,用起来很方便。

最后,播放界面是统一的,看起来顺眼。

浏览器兼容性

项目要求最低IE9,哎,这是个沉重而伤心的话题。

在实际操作中发现了这样情况(这些情况仅仅是个人总结,管中窥豹、盲人摸象,很片面):

  • IE9不支持video.js库,也不支持m3u8格式,因此要使用原生的video标签加载原始视频。
  • IE10支持video.js库,但不支持m3u8格式,因此要使用video.js加载原始视频。
  • 其他现代浏览器即支持video.js库,也支持m3u8格式,因此要使用video.js加载m3u8文件,分片播放.ts格式的视频。

实战部分


在项目中添加video.js库和类型定义文件@types/video.js
yarn add video.js
yarn add @types/video.js -D

额外说明一下:还得引入core-js库,因为不引用它的话,在IE9浏览器下会报脚本错误(又是那个伤心的话题,再次流泪,为我因此而消耗的时间流泪)。如果不用兼容IE9,可以不引用。

项目结构

由于项目是用webpack构建的,一些相关的配置就不详细叙述了,直接上代码吧。

最基本的项目结构.png

package.json代码:

{
  "name": "webpack-ts-videojs",
  "version": "0.0.0",
  "description": "在TypeScript项目中使用video.js",
  "scripts": {
    "build": "webpack",
    "start": "webpack-dev-server"
  },
  "author": "BigDipper",
  "license": "MIT",
  "dependencies": {
    "video.js": "^7.8.2",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.12"
  },
  "devDependencies": {
    "@types/video.js": "^7.3.10",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.6.0",
    "html-webpack-plugin": "^4.3.0",
    "style-loader": "^1.2.1",
    "ts-loader": "^7.0.5",
    "typescript": "^3.9.5",
    "webpack-dev-server": "^3.11.0"
  }
}

webpack.config.js代码:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
    mode: 'development',         // 模式,默认两种 production和development
    entry: './src/index.ts',    // 入口,从哪个文件开始打包
    output: {                   // 出口
        filename: 'bundle.js',  // 打包后的文件名
        path: path.resolve(__dirname, './build')   // 路径必须是一个绝对路径
    },
    devServer: {                // 开发服务器的配置
        port: 3000,             //端口
        progress: true,         // 打包时显示进度条
        compress: true,          // 启用gzip压缩
        proxy: { // 代理接口
            '/apis': {
                target: 'http://192.168.229.128:8080', // 后端联调地址
                changeOrigin: true,
                secure: false,
            },
        },
    },
    devtool: 'inline-source-map',
    module: {
        rules: [{
            test: /\.tsx?$/,
            use: 'ts-loader',
            exclude: /node_modules/
        }, {
            test: /\.css$/,
            use: [
                'style-loader', // 将 JS 字符串生成为 style 节点
                'css-loader',   // 将 CSS 转化成 CommonJS 模块
            ]
        }]
    },
    resolve: {
        extensions: ['.tsx', '.ts', '.js']
    },
    plugins: [  // 数组,放着所有的webpack插件
        new CleanWebpackPlugin({
            cleanAfterEveryBuildPatterns: ['build']
        }),
        new HtmlWebpackPlugin({
            template: './src/index.html',       // 指定要打包的模板
            filename: 'index.html',             // 打包后生成的文件
        })
    ]
};

就这么多吧,代码太长了没心思看下去,而且这也不是重点。

最基本的调用

index.html文件中,添加标签:




    
    
    Document


    


index.ts中引用video.js的库和样式,并调用:

import 'video.js/dist/video-js.css'
import videojs from 'video.js';

videojs(document.getElementById('myVideo'), {
    autoplay: false,
    controls: true,
    sources: [{
        src: '/apis/attachFiles/admin/2020/6/2016561465586925611.m3u8',
        type: 'application/x-mpegURL'
    }
    ]
});

之后,在命令行运行npm start,看效果:

现代浏览器:

现代浏览器.gif

IE10不支持m3u8

IE10不支持m3u8.png

IE9脚本报错

IE9脚本报错.png
升级代码,支持到IE9

思路:
针对这种情况,我们要做妥协让步,让IE10播放mp4文件,而不是m3u8文件,而IE9就直接用原生的videomp4文件,总之就是一个目的,能播放出视频就行了,就别管播放的是哪类文件,界面好不好看了,都是江湖儿女,不用拘泥于这些繁文缛节。

  1. 为了IE9,添加core-js库:
yarn add core-js
  1. 由于涉及到dom节点的操作,图省事儿,添加jquery库:
yarn add jquery
yarn add @types/jquery -D
  1. 删除index.html中的标签,代码如下:



    
    
    Document




  1. 新添加判断IE版本的模块IEVersion.ts,文档位置与index.ts平级,代码如下:
// 获取IE版本
export function IEVersion() {
    // 取得浏览器的userAgent字符串
    let userAgent = navigator.userAgent;
    // 判断是否为小于IE11的浏览器
    let isLessIE11 = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1;
    // 判断是否为IE的Edge浏览器
    let isEdge = userAgent.indexOf('Edge') > -1 && !isLessIE11;
    // 判断是否为IE11浏览器
    let isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1;
    if (isLessIE11) {
        let IEReg = new RegExp('MSIE (\\d+\\.\\d+);');
        // 正则表达式匹配浏览器的userAgent字符串中MSIE后的数字部分,,这一步不可省略!!!
        IEReg.test(userAgent);
        // 取正则表达式中第一个小括号里匹配到的值
        let IEVersionNum = parseFloat(RegExp['$1']);
        if (IEVersionNum === 7) {
            // IE7
            return 7
        } else if (IEVersionNum === 8) {
            // IE8
            return 8
        } else if (IEVersionNum === 9) {
            // IE9
            return 9
        } else if (IEVersionNum === 10) {
            // IE10
            return 10
        } else {
            // IE版本<7
            return 6
        }
    } else if (isEdge) {
        // edge
        return 'edge'
    } else if (isIE11) {
        // IE11
        return 11
    } else {
        // 不是ie浏览器
        return -1
    }
}
  1. 改造index.ts文件,引入jqueryIEVersion模块,为对应的浏览器添加适当的dom节点和播放视频,代码如下:
import 'core-js';
import $ from 'jquery';

import 'video.js/dist/video-js.css'
import videojs from 'video.js';

import { IEVersion } from './IEVersion';

let ieVersion = IEVersion();
let isIE9: boolean = ieVersion === 9;
let isIE10: boolean = ieVersion === 10;

if (isIE9) {    // ie9播放视频 原生的video标签
    $('body').append(`
        
   `);
} else {    // video.js播放
    let options: {autoplay: boolean, controls: boolean, language: string, sources: any[]} = {
        autoplay: false,
        controls: true,
        language: 'zh-CN',
        sources: []
    };

    if (isIE10) {   // ie10播放视频
        options.sources.push({
            src: '/apis/attachFiles/admin/2020/6/2016561465586925611.mp4',
            type: 'video/mp4'
        });
    } else {
        options.sources.push({
            src: '/apis/attachFiles/admin/2020/6/2016561465586925611.m3u8',
            type: 'application/x-mpegURL'
        });
    }

    $('body').append(``);
    videojs(document.getElementById('myVideo'), options);
}

如此这般之后,IE9IE10就都能播放了,如图所示:

ie9-原生video标签.gif
IE10-videojs.gif
进化一小下:修改样式、汉化
  • 把播放按钮弄圆

新建一个和index.ts同级的样式文件index.css,代码如下:

/* 播放按钮变圆形 */

.video-js .vjs-big-play-button{
    font-size: 2.5em;
    line-height: 2.3em;
    height: 2.5em;
    width: 2.5em;
    -webkit-border-radius: 2.5em;
    -moz-border-radius: 2.5em;
    border-radius: 2.5em;
    background-color: #73859f;
    background-color: rgba(115,133,159,.5);
    border-width: 0.15em;
    margin-top: -1.25em;
    margin-left: -1.75em;
}
/* 中间的播放箭头 */
.vjs-big-play-button .vjs-icon-placeholder {
    font-size: 1.63em;
}
/* 加载圆圈 */
.vjs-loading-spinner {
    font-size: 2.5em;
    width: 2em;
    height: 2em;
    border-radius: 1em;
    margin-top: -1em;
    margin-left: -1.5em;
}

index.ts中引入此样式:

...

import { IEVersion } from './IEVersion';

import './index.css'

let ieVersion = IEVersion();
let isIE9: boolean = ieVersion === 9;

...

然后,按钮就变样了:


图片.png
  • 汉化这个事儿比较头疼,我之前是直接在index.ts文件中引入了video.js/dist/lang/zh-CN.js文件,但是会报错,提示没有videojs这个对象,所以现在就用了个简单粗暴的法子,将zh-CN.js文件的内容拷贝到了index.ts中,代码如下:
...

} else {
        ptions.sources.push({
            src: '/apis/attachFiles/admin/2020/6/2016561465586925611.m3u8',
            type: 'application/x-mpegURL'
        });
    }

// 汉化设置
        // 由于引入/node_modules/video.js/dist/lang/zh-CN.js会报错,因此将此文件内容复制过来了。
        // 其实也用不了这么多汉化,但我真的是不想再摘出来了,累了。

        videojs.addLanguage('zh-CN', {
            "Play": "播放",
            "Pause": "暂停",
            "Current Time": "当前时间",
            "Duration": "时长",
            "Remaining Time": "剩余时间",
            "Stream Type": "媒体流类型",
            "LIVE": "直播",
            "Loaded": "加载完成",
...
}

$('body').append(``);
...

效果如下:


图片.png

这是项目最终的结构图,只是为了说明问题,真实项目中可千万别这么分类,太乱:


图片.png

好了,就这些吧,头疼,得吃点了。

你可能感兴趣的:(在TypeScript中使用video.js)