You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel项目加密视频在Video.js播放时addEventListener及广告插件报错

解决Video.js + IMA广告初始化时机错误及事件监听失效问题

问题分析

  1. 初始化时机错误:你添加的data-setup='{}'会触发Video.js自动初始化播放器,而你又在DOMContentLoaded回调里手动调用videojs(video.id),导致播放器重复初始化。IMA广告依赖的videojs-contrib-ads要求在播放器初始化后的同一事件循环内加载,自动初始化提前触发了loadstart事件,后续手动加载插件就会错过时机,触发报错。
  2. 事件监听失效:Video.js会封装原生video元素,直接给原生video绑定addEventListener可能被播放器的事件系统拦截,导致无法触发,应该使用Video.js播放器实例的事件绑定方法。

解决方案

1. 移除自动初始化属性

删除video标签中的data-setup='{}',完全由代码手动初始化播放器,确保流程可控。

修改后的视图代码:

<video class="img-fluid myVideo video-js vjs-default-skin" id="content_video{{ $video_list->id }}" preload="none" controls data-video-id="{{ Crypt::encrypt($video_list->id) }}">
    @if (Auth::check())
        <source src="{{ route('video.player.show', ['filename' => $video_list->unique_number.'.m3u8','type' => 'full','video_id' => $video_list->unique_number]) }}" type="application/x-mpegURL" class="full-video">
    @endif
</video>

2. 调整JS代码,确保插件及时初始化并使用Video.js事件系统

  • 替换原生video元素的事件监听为player.on()绑定
  • 确保IMA插件在播放器实例创建后立即初始化
  • 修正options中的id为当前视频的实际id

修改后的JS代码:

<script>
document.addEventListener('DOMContentLoaded', function() {
    console.log('afterload');
    const videos = document.querySelectorAll('.myVideo');
    let playing = [];

    videos.forEach((video, index) => {
        console.log('video');
        console.log(video.id);
        const overlay = document.querySelectorAll('.overlay')[index];
        const paymentoverlay = document.querySelectorAll('.paymentoverlay')[index];

        // 手动初始化播放器,完全控制初始化流程
        const player = videojs(video.id);

        // 修正options中的id为当前视频的实际id
        var options = {
            id: video.id,
            adTagUrl: 'http://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=xml_vmap1&unviewed_position_start=1&cust_params=sample_ar%3Dpremidpostpod%26deployment%3Dgmf-js&cmsid=496&vid=short_onecue&correlator='
        };

        // 创建播放器后立即初始化IMA插件,确保在同一事件循环内完成
        player.ima(options);

        // 使用Video.js播放器实例绑定ended事件
        player.on('ended', function() {
            console.log('111');
            handleVideoConditions(video, overlay, paymentoverlay);
        });

        // 使用Video.js的play事件,替代原生onplay
        player.on('play', function() {
            playing.push(video);
            if (!player.paused()) {
                player.controls(true);
                registerView(video);
            }
        });
    });

    function handleVideoConditions(video, overlay, paymentoverlay) {
        console.log('222');
        const isShortVideo = video.querySelector('.short-video');
        const isFullVideo = video.querySelector('.full-video');
        if (!isUserLoggedIn && isShortVideo) {
            overlay.style.display = 'block';
        } else if (isUserLoggedIn && isShortVideo) {
            paymentoverlay.style.display = 'block';
        }
    }

    async function registerView(video) {
        const videoId = video.getAttribute('data-video-id');
        const response = await fetch(`{{ route('video.registerView', ['videoId' => ':videoId']) }}`
            .replace(':videoId', videoId));
        const data = await response.json();
        $('#videoview' + data.id).html(data.view_count);
    }

});
</script>

额外说明

  • 手动初始化后,所有视频相关事件都要通过Video.js的player.on()绑定,确保事件被正确捕获,避免原生事件被封装层拦截。
  • 移除data-setup后,播放器初始化完全由代码控制,从根源上解决了videojs-contrib-ads初始化时机过晚的问题,插件在播放器创建后的同一代码块内立即初始化,符合要求的"同一事件循环"条件。

内容的提问来源于stack exchange,提问作者vinod

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 07:47:41