解读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;
}