VideoJs使用介绍

小占时光 2023-09-19 10:20:17 3294


介绍   

      每次用videojs都去找api,找了半天,记录一下,方便以后使用。

   Video.js 是一个开源的 HTML5 视频播放器库,它允许开发者在网站或应用程序中嵌入自定义的视频播放器。Video.js 提供了一个强大的基础框架,可用于创建高度可定制的视频播放器,具有各种功能和外观选项。Video.js 提供了一个强大的 JavaScript API,允许开发者对播放器进行高度定制和控制。你可以通过 API 控制播放、暂停、音量、时间轴等。

官网地址 ➤ https://videojs.com/ 

github地址 ➤ https://github.com/videojs/video.js

 

简单使用

项目需要添加的文件         
// video.js
"@node_modules/video.js/dist/*.js": "@libs/video.js/dist/",
"@node_modules/video.js/dist/*.css": "@libs/video.js/dist/",
"@node_modules/video.js/dist/alt/**": "@libs/video.js/dist/alt/",
"@node_modules/video.js/dist/font/**": "@libs/video.js/dist/font/",

页面需要引入的css和js
<link rel="stylesheet" href="/libs/video.js/dist/video-js.min.css" />
<script src="/libs/video.js/dist/video.min.js"></script>

官网给的例子比较简单

HTML:

<video
    id="my-player"
    class="video-js"
    controls
    preload="auto"
    poster="//vjs.zencdn.net/v/oceans.png"
    data-setup='{}'>
  <source src="//vjs.zencdn.net/v/oceans.mp4" type="video/mp4"></source>
  <source src="//vjs.zencdn.net/v/oceans.webm" type="video/webm"></source>
  <source src="//vjs.zencdn.net/v/oceans.ogv" type="video/ogg"></source>
  <p class="vjs-no-js">
    To view this video please enable JavaScript, and consider upgrading to a
    web browser that
    <a href="https://videojs.com/html5-video-support/" target="_blank">
      supports HTML5 video
    </a>
  </p>
</video>
JS:

var options = {};

var player = videojs('my-player', options, function onPlayerReady() {
  videojs.log('Your player is ready!');

  // In this context, `this` is the player that was created by Video.js.
  this.play();

  // How about an event listener?
  this.on('ended', function() {
    videojs.log('Awww...over so soon?!');
  });
});

官网给的信息有点少,所有只能去找api,这点东西根本不能灵活运用。

 

Videojs API

        在项目文件下发现一个新大陆,就是api.js ,这个里面记录了几乎所有api,之前还一直未发现。 

先介绍用法, 例如:player 是页面videojs实例, assert.ok(player.src, 'src exists'); 用的时候只要 player.src()  加括号,原来他就是一个方法,所以像方法一样调用即可,下面列就是这些api了(直接复制过来)

// Native HTML5 Methods
  assert.ok(player.error, 'error exists');
  assert.ok(player.src, 'src exists');
  assert.ok(player.currentSrc, 'currentSrc exists');
  assert.ok(player.buffered, 'buffered exists');
  assert.ok(player.load, 'load exists');
  assert.ok(player.seeking, 'seeking exists');
  assert.ok(player.currentTime, 'currentTime exists');
  assert.ok(player.duration, 'duration exists');
  assert.ok(player.paused, 'paused exists');
  assert.ok(player.ended, 'ended exists');
  assert.ok(player.autoplay, 'autoplay exists');
  assert.ok(player.loop, 'loop exists');
  assert.ok(player.play, 'play exists');
  assert.ok(player.pause, 'pause exists');
  assert.ok(player.controls, 'controls exists');
  assert.ok(player.volume, 'volume exists');
  assert.ok(player.muted, 'muted exists');
  assert.ok(player.width, 'width exists');
  assert.ok(player.height, 'height exists');
  assert.ok(player.poster, 'poster exists');
  assert.ok(player.textTracks, 'textTracks exists');
  assert.ok(player.requestFullscreen, 'requestFullscreen exists');
  assert.ok(player.exitFullscreen, 'exitFullscreen exists');
  assert.ok(player.disablePictureInPicture, 'disablePictureInPicture exists');
  assert.ok(player.requestPictureInPicture, 'requestPictureInPicture exists');
  assert.ok(player.exitPictureInPicture, 'exitPictureInPicture exists');
  assert.ok(player.playbackRate, 'playbackRate exists');
  assert.ok(player.networkState, 'networkState exists');
  assert.ok(player.readyState, 'readyState exists');

  // Unsupported Native HTML5 Methods
  // assert.ok(player.canPlayType, 'canPlayType exists');
  // assert.ok(player.startTime, 'startTime exists');
  // assert.ok(player.defaultPlaybackRate, 'defaultPlaybackRate exists');
  // assert.ok(player.playbackRate, 'playbackRate exists');
  // assert.ok(player.played, 'played exists');
  // assert.ok(player.seekable, 'seekable exists');
  // assert.ok(player.videoWidth, 'videoWidth exists');
  // assert.ok(player.videoHeight, 'videoHeight exists');

  // Additional player methods
  assert.ok(player.bufferedPercent, 'bufferedPercent exists');
  assert.ok(player.reportUserActivity, 'reportUserActivity exists');
  assert.ok(player.userActive, 'userActive exists');
  assert.ok(player.usingNativeControls, 'usingNativeControls exists');
  assert.ok(player.isFullscreen, 'isFullscreen exists');
  assert.ok(player.getVideoPlaybackQuality, 'getVideoPlaybackQuality exists');

  // Track methods
  assert.ok(player.audioTracks, 'audioTracks exists');
  assert.ok(player.videoTracks, 'videoTracks exists');
  assert.ok(player.textTracks, 'textTracks exists');
  assert.ok(player.remoteTextTrackEls, 'remoteTextTrackEls exists');
  assert.ok(player.remoteTextTracks, 'remoteTextTracks exists');
  assert.ok(player.addTextTrack, 'addTextTrack exists');
  assert.ok(player.addRemoteTextTrack, 'addRemoteTextTrack exists');
  assert.ok(player.removeRemoteTextTrack, 'removeRemoteTextTrack exists');

  // Deprecated methods that should still exist
  assert.ok(player.requestFullScreen, 'requestFullScreen exists');
  assert.ok(player.isFullScreen, 'isFullScreen exists');
  assert.ok(player.cancelFullScreen, 'cancelFullScreen exists');

 

下面几个在下并没有测试过,记录下来,有需要的可以自行使用

QUnit.test('should be able to access expected component API methods', function(assert) {
  const Component = videojs.getComponent('Component');
  const comp = new Component({
    id() {
      return 1;
    },
    reportUserActivity() {}
  });

  // Component methods
  assert.ok(comp.player, 'player exists');
  assert.ok(comp.options, 'options exists');
  assert.ok(comp.init, 'init exists');
  assert.ok(comp.dispose, 'dispose exists');
  assert.ok(comp.createEl, 'createEl exists');
  assert.ok(comp.contentEl, 'contentEl exists');
  assert.ok(comp.el, 'el exists');
  assert.ok(comp.addChild, 'addChild exists');
  assert.ok(comp.getChild, 'getChild exists');
  assert.ok(comp.getChildById, 'getChildById exists');
  assert.ok(comp.children, 'children exists');
  assert.ok(comp.initChildren, 'initChildren exists');
  assert.ok(comp.removeChild, 'removeChild exists');
  assert.ok(comp.on, 'on exists');
  assert.ok(comp.off, 'off exists');
  assert.ok(comp.one, 'one exists');
  assert.ok(comp.trigger, 'trigger exists');
  assert.ok(comp.triggerReady, 'triggerReady exists');
  assert.ok(comp.show, 'show exists');
  assert.ok(comp.hide, 'hide exists');
  assert.ok(comp.width, 'width exists');
  assert.ok(comp.height, 'height exists');
  assert.ok(comp.dimensions, 'dimensions exists');
  assert.ok(comp.ready, 'ready exists');
  assert.ok(comp.addClass, 'addClass exists');
  assert.ok(comp.removeClass, 'removeClass exists');
  assert.ok(comp.buildCSSClass, 'buildCSSClass exists');
  assert.ok(comp.setInterval, 'setInterval exists');
  assert.ok(comp.clearInterval, 'clearInterval exists');
  assert.ok(comp.setTimeout, 'setTimeout exists');
  assert.ok(comp.clearTimeout, 'clearTimeout exists');

  comp.dispose();
});

QUnit.test('should be able to access expected MediaTech API methods', function(assert) {
  const media = videojs.getComponent('Tech');
  const mediaProto = media.prototype;
  const html5 = videojs.getComponent('Html5');
  const html5Proto = html5.prototype;

  assert.ok(mediaProto.setPoster, 'setPoster should exist on the Media tech');
  assert.ok(html5Proto.setPoster, 'setPoster should exist on the HTML5 tech');

  assert.ok(html5.patchCanPlayType, 'patchCanPlayType should exist for HTML5');
  assert.ok(html5.unpatchCanPlayType, 'unpatchCanPlayType should exist for HTML5');

  // Source Handler Functions
  assert.ok(media.withSourceHandlers, 'withSourceHandlers should exist for Media Tech');

  assert.ok(html5.canPlaySource, 'canPlaySource should exist for HTML5');
  assert.ok(html5.registerSourceHandler, 'registerSourceHandler should exist for Html5');
  assert.ok(html5.selectSourceHandler, 'selectSourceHandler should exist for Html5');
  assert.ok(html5.prototype.setSource, 'setSource should exist for Html5');
  assert.ok(html5.prototype.disposeSourceHandler,
           'disposeSourceHandler should exist for Html5');
});

QUnit.test('should export ready api call to public', function(assert) {
  const videoTag = testHelperMakeTag();
  const fixture = document.getElementById('qunit-fixture');

  fixture.appendChild(videoTag);

  const player = videojs('example_1');

  assert.ok(player.ready !== undefined, 'ready callback is defined');
  player.dispose();
});

QUnit.test('should export useful components to the public', function(assert) {
  assert.ok(videojs.browser.TOUCH_ENABLED !== undefined,
           'Touch detection should be public');
  assert.ok(videojs.getComponent('ControlBar'), 'ControlBar should be public');
  assert.ok(videojs.getComponent('Button'), 'Button should be public');
  assert.ok(videojs.getComponent('PlayToggle'), 'PlayToggle should be public');
  assert.ok(videojs.getComponent('PictureInPictureToggle'), 'PictureInPictureToggle should be public');
  assert.ok(videojs.getComponent('FullscreenToggle'), 'FullscreenToggle should be public');
  assert.ok(videojs.getComponent('BigPlayButton'), 'BigPlayButton should be public');
  assert.ok(videojs.getComponent('LoadingSpinner'), 'LoadingSpinner should be public');
  assert.ok(videojs.getComponent('CurrentTimeDisplay'),
           'CurrentTimeDisplay should be public');
  assert.ok(videojs.getComponent('DurationDisplay'), 'DurationDisplay should be public');
  assert.ok(videojs.getComponent('TimeDivider'), 'TimeDivider should be public');
  assert.ok(videojs.getComponent('RemainingTimeDisplay'),
           'RemainingTimeDisplay should be public');
  assert.ok(videojs.getComponent('Slider'), 'Slider should be public');
  assert.ok(videojs.getComponent('ProgressControl'), 'ProgressControl should be public');
  assert.ok(videojs.getComponent('SeekBar'), 'SeekBar should be public');
  assert.ok(videojs.getComponent('LoadProgressBar'), 'LoadProgressBar should be public');
  assert.ok(videojs.getComponent('PlayProgressBar'), 'PlayProgressBar should be public');
  assert.ok(videojs.getComponent('VolumeControl'), 'VolumeControl should be public');
  assert.ok(videojs.getComponent('VolumeBar'), 'VolumeBar should be public');
  assert.ok(videojs.getComponent('VolumeLevel'), 'VolumeLevel should be public');
  assert.ok(videojs.getComponent('VolumeMenuButton'), 'VolumeMenuButton should be public');
  assert.ok(videojs.getComponent('MuteToggle'), 'MuteToggle should be public');
  assert.ok(videojs.getComponent('PosterImage'), 'PosterImage should be public');
  assert.ok(videojs.getComponent('Menu'), 'Menu should be public');
  assert.ok(videojs.getComponent('MenuItem'), 'MenuItem should be public');
  assert.ok(videojs.getComponent('MenuButton'), 'MenuButton should be public');
  assert.ok(videojs.getComponent('PlaybackRateMenuButton'),
           'PlaybackRateMenuButton should be public');

  assert.ok(videojs.getComponent('CaptionSettingsMenuItem'),
           'CaptionSettingsMenuItem should be public');
  assert.ok(videojs.getComponent('OffTextTrackMenuItem'),
           'OffTextTrackMenuItem should be public');
  assert.ok(videojs.getComponent('TextTrackMenuItem'),
           'TextTrackMenuItem should be public');
  assert.ok(videojs.getComponent('TextTrackDisplay'), 'TextTrackDisplay should be public');
  assert.ok(videojs.getComponent('TextTrackButton'), 'TextTrackButton should be public');
  assert.ok(videojs.getComponent('CaptionsButton'), 'CaptionsButton should be public');
  assert.ok(videojs.getComponent('SubtitlesButton'), 'SubtitlesButton should be public');
  assert.ok(videojs.getComponent('DescriptionsButton'),
           'DescriptionsButton should be public');
  assert.ok(videojs.getComponent('ChaptersButton'), 'ChaptersButton should be public');
  assert.ok(videojs.getComponent('ChaptersTrackMenuItem'),
           'ChaptersTrackMenuItem should be public');

  assert.ok(videojs.mergeOptions, 'mergeOptions should be public');
});

QUnit.test('should be able to initialize player twice on the same tag using string reference', function(assert) {
  const videoTag = testHelperMakeTag();
  const id = videoTag.id;
  const fixture = document.getElementById('qunit-fixture');

  fixture.appendChild(videoTag);

  const player = videojs('example_1');

  player.dispose();
  assert.ok(!document.getElementById(id), 'element is removed');

  videoTag = testHelperMakeTag();
  fixture.appendChild(videoTag);

  player = videojs('example_1');
  player.dispose();
});

QUnit.test('videojs.getPlayers() should be available after minification', function(assert) {
  const videoTag = testHelperMakeTag();
  const id = videoTag.id;
  const fixture = document.getElementById('qunit-fixture');

  fixture.appendChild(videoTag);

  const player = videojs(id);

  assert.ok(videojs.getPlayers()[id] === player, 'videojs.getPlayers() is available');

  player.dispose();
});

QUnit.test('component can be subclassed externally', function(assert) {
  const Component = videojs.getComponent('Component');
  const ControlBar = videojs.getComponent('ControlBar');

  class TestComponent extends Component {
    reportUserActivity() {}
    textTracks() {
      return {
        addEventListener: Function.prototype,
        removeEventListener: Function.prototype
      };
    }
  }

  const player = new TestComponent({
    id() {},
    reportUserActivity() {}
  });

  assert.ok(new ControlBar(player), 'created a control bar without throwing');
});

function testHelperMakeTag() {
  const videoTag = document.createElement('video');

  videoTag.id = 'example_1';
  videoTag.className = 'video-js';
  return videoTag;
}

QUnit.test('should extend Component', function(assert) {
  const Component = videojs.getComponent('Component');

  class MyComponent extends Component {
    constructor() {
      this.bar = true;
    }
    foo() {
      return true;
    }
  }

  const myComponent = new MyComponent();

  assert.ok(myComponent instanceof Component, 'creates an instance of Component');
  assert.ok(myComponent instanceof MyComponent, 'creates an instance of MyComponent');
  assert.ok(myComponent.bar, 'the constructor function is used');
  assert.ok(myComponent.foo(), 'instance methods are applied');

  class NoMethods extends Component {}

  const noMethods = new NoMethods({});

  assert.ok(noMethods.on, 'should extend component with no methods or constructor');

  myComponent.dispose();

 

实战运用

         自己在开发中用到了,修改videojs页面样式,还有自定义按钮,全屏时自定义按钮可以随着播放器一起全屏。下面是一些配置介绍

video 配置按钮显示是可以多出配置,会重复显示,要在optins 的hildren 中配置即可
inactivityTimeout 标识控制条隐藏时间
var options = {
controls: true, fluid: true,inactivityTimeout :0,//控制条一直显示
playbackRates: [0.5, 1, 1.5, 2, 2.5],
controlBar: {
//CurrentTimeDisplay: true, // 当前时间

}}

 

部分按钮设置了也不会一直显示直接修改样式
.video-js .vjs-time-control {
display: block;
}

videojs 恢复到初始状态显示封面
this.player.hasStarted(false);

示例代码


JS: 

// 初始化播放器
        videojs('player-@video.Id', {
            controls: true,
            loop: false,
            inactivityTimeout: 0,//控制条一直显示
            playbackRates: [0.5, 1.0, 1.5, 2.0, 2.5], // 播放速度
            controlBar: {
                // 自定义按钮的位置
                children: [
                    { name: 'playToggle' }, // 播放按钮
                    { name: 'currentTimeDisplay' },
                    { name: 'TimeDivider' }, // 当前已播放时间
                    { name: 'durationDisplay' }, // 当前已播放时间
                    { name: 'progressControl' }, // 播放进度条
                    {
                        name: 'playbackRateMenuButton',// 倍数播放
                    },
                    {
                        name: 'volumePanel', // 音量控制
                        inline: false, // 不使用水平方式
                    },
                    { name: 'FullscreenToggle' },// 全屏
                ]
            },
        }, function onPlayerReady(e) {

            var eleId = this.id();
            // 播放器标签
            var element = $('#' + eleId);
            var dataId = element.data('id');

            // 添加自定义按钮
            addButton(dataId, element);

            this.on("playing", function () { // 监听播放
                //console.log("开始播放")
            })
            this.on("pause", function () {
                //console.log("暂停");
            });
        });

        // 播放器添加按钮
        function addButton(dataId, element) {

            // 添加详情按钮
            var detailbtn = document.createElement('btn');
            detailbtn.className = "custom-video-button";
            detailbtn.innerHTML = '<button class="vjs-control" data-id=' + dataId + ' data-action="detail" > '
                + ' <span class="detail-text"></span> 详情 > </button>';

            var controlBar = element.find('.vjs-control-bar')[0];
            insertBeforeNode = element.find('.vjs-fullscreen-control')[0];
            controlBar.insertBefore(detailbtn, insertBeforeNode.nextSibling);

            // 添加是否连续播放
            var checkBox = '<div data-action="check" class="form-check form-switch">' +
                '<input  class="form-check-input" type="checkbox" role="switch" id="flexSwitchCheckChecked" >' +
                '<label class="form-check-label" for="flexSwitchCheckChecked">自动连播</label>' +
                '</div>';

            var checkBtn = document.createElement('btn');
            checkBtn.className = "custom-video-button";
            checkBtn.innerHTML = checkBox;
            var checkInsertBeforeNode = element.find('.vjs-duration')[0];
            controlBar.insertBefore(checkBtn, checkInsertBeforeNode.nextSibling);
        }

 

参考CSS 页面样式调整:



/*播放器样式*/
.my-video-player, .my-video-player .player { width: 100%; height: 100%; position: relative; }
.my-video-player .video-js .vjs-progress-control { position: absolute !important; top: -10px; width: 100% !important; }

/* .my-video-player .vjs-has-started .vjs-control-bar, .vjs-audio-only-mode .vjs-control-bar {position: relative;} */
.my-video-player .video-js .vjs-control { height: auto !important; font-weight: bolder; }
/* 控制条高度调整结束 */

.my-video-player .video-js .vjs-progress-control .vjs-progress-holder { margin: 0px !important; }

.my-video-player .vjs-control-bar { display: none; }
/*进度条高度*/
.my-video-player .video-js .vjs-progress-holder { height: 6px; }
/* 进度调试初始化就显示出来 */
.my-video-player .video-js .vjs-control-bar { display: flex !important; z-index: 100; background: transparent; }
/*不显示初始播放的 大按钮*/
.my-video-player .vjs-big-play-button { display: none !important; }

.my-video-player .video-js { width: 100%; height: 100%; }

/* 自定义控件开始 */
.my-video-player .vjs-control-bar .my-video-button { margin-left: auto !important; }

.my-video-player .vjs-control-bar .my-video-button .vjs-control { height: 100% !important; width: 70px !important; cursor: pointer; }
/* 自定义控件结束 */

/*视频留出控制条位置开始,封面图显示设置*/
.my-video-player .video-js .vjs-tech { padding-bottom: 40px !important; }
.my-video-player .vjs-poster { display: none; }

.my-video-player .vjs-poster { height: auto !important; margin-bottom: 30px !important; }
/*视频留出控制条位置结束*/

/* 播放时间开始*/
.video-js .vjs-duration { display: block !important; padding-left: 3px !important; color: #f5f3f352 !important; }

.video-js .vjs-current-time { display: block !important; padding-right: 3px !important; }

/*分割线*/
.video-js .vjs-time-divider { padding: 0px !important; min-width: auto !important; display: block !important; }
/* 播放时间结束*/

/* 播放速度,声音调整开始*/
.my-video-player .vjs-menu-button-popup .vjs-menu { bottom: -6px !important; }

.my-video-player .vjs-volume-bar.vjs-slider-vertical { height: 6em !important; }

.my-video-player .video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-vertical { height: 110px !important; }
/* 播放速度,声音调整结束*/

.my-video-player .video-js .detail-text { border-left: 1px solid #c9c9c969; margin-right: 15px; }

/* 所有图标靠右 */
.my-video-player .video-js .vjs-playback-rate, .my-video-player .video-js .vjs-volume-panel, .my-video-player .video-js .vjs-fullscreen-control,
.my-video-player .vjs-control-bar .my-video-button { margin-left: auto !important; }

/*进度条的原点去掉*/
.my-video-player .video-js .vjs-play-progress:before { content: "" !important; }

 

事件监听示例


          
  var player = videojs(item);
        player.on("playing", function (e) {
            // 播放立即全屏
            player.requestFullscreen();
        })
        player.on('ended', function () {
            // 结束退出全屏
            player.exitFullscreen();
        });

        player.on('fullscreenchange', (e) => {
            // 退出全屏暂停播放
            if (!player.isFullscreen()) {
                player.pause();
            }
        })

 

 

最后一次修改 : 2025/4/29 上午10:19:34

优秀
123
分享
123
奶茶
123
文章版权声明:版权归原作者(小占时光)所有。未经明确书面许可,严禁任何个人或组织以任何形式进行商业性或非商业性的使用、转载或抄袭。
评论