解读flvjs源码 第2篇 创建指定类型播放器,添加事件和相关属

2020-09-21  本文已影响0人  Kason晨

先上一个createPlayer 创建播放器的demo。

<script src="flv.min.js"></script>
<video id="videoElement"></video>
<script>
//先检测flvjs是否被支持
    if (flvjs.isSupported()) {
//如果支持,就再获取DOM节点,然后调用createPlayer方法创建播放器
        var videoElement = document.getElementById('videoElement');
        var flvPlayer = flvjs.createPlayer({
            type: 'flv',
            url: 'http://example.com/flv/video.flv'
        });
        flvPlayer.attachMediaElement(videoElement);
        flvPlayer.load();
        flvPlayer.play();
    }
</script>

在flvjs的源码里createPlayer是这么个思路:
1,传入一些配置信息,先检查传入的对象是否是null或object,如果都不满足,就抛出一个错误。
2,再检查配置信息是否指明了类型,即type。入股没有,也会报一个异常。
3,若指明了type,则会根据type觉得创建flv播放器还是原生的video播放器(NativePlayer)

//flv.js/src/flv.js  源码的位置
// factory method
//optionalConfig暂时没发现第二个参数optionalConfig有什么用,因为没传值也完整可以正常使用,看源码最后也是和前面的参数mediaDataSource合并在一起了。
//源码位置:flv.js/src/player/flv-player.js 的 constructor构造器里
function createPlayer(mediaDataSource, optionalConfig) {
//传入一些配置信息,先检查传入的对象是否是null或object,如果都不满足,就抛出一个错误。
    let mds = mediaDataSource;
    if (mds == null || typeof mds !== 'object') {
        throw new InvalidArgumentException('MediaDataSource must be an javascript object!');
    }
//再检查配置信息是否指明了类型,即type。入股没有,也会报一个异常。
    if (!mds.hasOwnProperty('type')) {
        throw new InvalidArgumentException('MediaDataSource must has type field to indicate video file type!');
    }
//若指明了type,则会根据type觉得创建flv播放器还是原生的video播放器
    switch (mds.type) {
        case 'flv':
            return new FlvPlayer(mds, optionalConfig);
        default:
            return new NativePlayer(mds, optionalConfig);
    }
}

这是我使用时的一些配置,没有写第二个参数。

        this.flvPlayer = flvjs.createPlayer({
          type: "flv",
          url: 动态设置,
          fixAudioTimestampGap: true,
          muted: true,
          isLive: true, //指示数据源是否为实时流
          hasAudio: true,
          cors: true, //指示是否启用CORS进行http提取
          enableWorker: false, //启用分离的线程进行转换(暂时不稳定)
          enableStashBuffer: true, //启用IO隐藏缓冲区。如果您需要实时(最小延迟)来进行实时流播放,则设置为false,但是如果网络抖动,则可能会停顿。
          stashInitialSize: 384, //指示IO暂存缓冲区的初始大小。默认值为384KB。指出合适的尺寸可以改善视频负载/搜索时间
          autoCleanupSourceBuffer: true, //对SourceBuffer进行自动清理
          autoCleanupMaxBackwardDuration: 2 * 60,
          autoCleanupMinBackwardDuration: 1 * 60
        });

检查是否提供了MSE,H264和其他一些属性。具体还要看/flv.js/src/core/features.js里的内容。

//flv.js/src/flv.js  源码的位置
// feature detection
//检查是否提供了MSE,H264
function isSupported() {
    return Features.supportMSEH264Playback();
}

//检查是否支持Mse,直播流,H264,VP8,VP9等信息
function getFeatureList() {
    return Features.getFeatureList();
}

创建一个对象把创建播放器对象的结果,是否浏览器是否支持这种播放器,编码相关的属性,一些事件和控制等,都封装进flvjs对象

//flv.js/src/flv.js  源码的位置
// interfaces
let flvjs = {};

flvjs.createPlayer = createPlayer;
flvjs.isSupported = isSupported;
flvjs.getFeatureList = getFeatureList;

flvjs.BaseLoader = BaseLoader;
flvjs.LoaderStatus = LoaderStatus;
flvjs.LoaderErrors = LoaderErrors;

flvjs.Events = PlayerEvents;
flvjs.ErrorTypes = ErrorTypes;
flvjs.ErrorDetails = ErrorDetails;

flvjs.FlvPlayer = FlvPlayer;
flvjs.NativePlayer = NativePlayer;
flvjs.LoggingControl = LoggingControl;

//用来返回版本等信息
Object.defineProperty(flvjs, 'version', {
    enumerable: true,
    get: function () {
        // replaced by browserify-versionify transform
        return '__VERSION__';
    }
});

export default flvjs;

现在再说一下features.js 东西都再注释里了。

//flv.js/src/core/features.js

//这些都是一些判定方法,等会供getFeatureList调用
    static supportMSEH264Playback() {
        return window.MediaSource &&
               window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"');
    }

    static supportNetworkStreamIO() {
        let ioctl = new IOController({}, createDefaultConfig());
        let loaderType = ioctl.loaderType;
        ioctl.destroy();
        return loaderType == 'fetch-stream-loader' || loaderType == 'xhr-moz-chunked-loader';
    }

    static getNetworkLoaderTypeName() {
        let ioctl = new IOController({}, createDefaultConfig());
        let loaderType = ioctl.loaderType;
        ioctl.destroy();
        return loaderType;
    }

    static supportNativeMediaPlayback(mimeType) {
        if (Features.videoElement == undefined) {
            Features.videoElement = window.document.createElement('video');
        }
        let canPlay = Features.videoElement.canPlayType(mimeType);
        return canPlay === 'probably' || canPlay == 'maybe';
    }

//加了static 应该可以直接调用,类似java的静态方法。
    static getFeatureList() {
//定义对象里的一些属性,等下再调用方法判断是否支持,把结果赋值给这些属性。
        let features = {
            mseFlvPlayback: false,
            mseLiveFlvPlayback: false,
            networkStreamIO: false,
            networkLoaderName: '',
            nativeMP4H264Playback: false,
            nativeWebmVP8Playback: false,
            nativeWebmVP9Playback: false
        };

        features.mseFlvPlayback = Features.supportMSEH264Playback();
        features.networkStreamIO = Features.supportNetworkStreamIO();
        features.networkLoaderName = Features.getNetworkLoaderTypeName();
        features.mseLiveFlvPlayback = features.mseFlvPlayback && features.networkStreamIO;
        features.nativeMP4H264Playback = Features.supportNativeMediaPlayback('video/mp4; codecs="avc1.42001E, mp4a.40.2"');
        features.nativeWebmVP8Playback = Features.supportNativeMediaPlayback('video/webm; codecs="vp8.0, vorbis"');
        features.nativeWebmVP9Playback = Features.supportNativeMediaPlayback('video/webm; codecs="vp9"');

        return features;
    }

上一篇下一篇

猜你喜欢

热点阅读