综合

1. 综合演示

2. 操作说明

  • 1、open、close、destroy 按钮: 分别对应打开、关闭、销毁播放器

  • 2、URL 输入框: 对应播放的视频URL

  • 3、Live 选项:表示是否是直播流

  • 4、Use Flv 选项:表示是否优先使用flv格式播放

  • 5、DANMU 输入框: 输入弹幕内容,

  • 6、Send Danmu、Enable Danmu、Disable Danmu 按钮: 分别对应发送弹幕、允许弹幕、禁止弹幕,注意:只是本地测试,并未发送到弹幕服务器。

  • 7、Load Chapters 按钮: 加载视频章节

  • 8、Load Subtitle、Remove Subtitle 按钮: 分别对应加载字幕、移除字幕

  • 9、MStreams 按钮:点开后弹出输入框,可输入多个视频源,支持多种格式,具体参看源地址url参数说明

    1. 1、json对象

      {
          "HD1": "https://example.com/stream-hd.flv",
          "SD1": "https://example.com/stream-ld.flv ",
          "SD2": "https://example.com/stream-sd.flv"
      }

       

    2. 2、json列表 方式一: 每个列表项对应一个json对象,包含name和url两个属性,name表示视频源的名称,url表示视频源的URL

      [
          {
              "name": "HD1",
              "url": "https://example.com/media/stream-hd.flv"
          },
          {
              "name": "SD1",
              "url": "https://example.com/media/stream-ld.flv",
              "default": true
          },
          {
              "name": "SD2",
              "url": "https://example.com/media/stream-sd.flv"
          }
      ]
    3. 3、json列表 方式二: 每个列表项对应一个列表:第0个位置为url;第1个位置为流的名称name,可以缺省;第2个位置为mime类型,通常缺省。

      [
          [
              "https://example.com/stream-uhd.flv",
              "HD1"
          ],
          [
              "https://example.com/stream-hd.flv",
              "SD1"
          ],
          [
              "https://example.com/stream-ld.flv",
              "SD2"
          ]
      ]

       

  • 10、stream_type 列表框: 选择视频源的格式,可选值有: httpflv、hls、dash、webrtc、mpegts

  • 11、CurrentTime 按钮: 获得当前时间

  • 12、Start、End、diffTime 显示:表示开始时间、结束时间、时间差(毫秒),可看到一个输入源从打开到开始播放需要的耗时

3. 注意事项

  1. 1、测试rtsp协议,需要开启媒体网关服务器,具体参看播放rtsp流

  2. 2、自带弹幕UI发送弹幕,需要开启弹幕服务器,具体参看弹幕设置说明

  3. 3、如需测试rtsp协议、弹幕功能,请加微信号: chenfanyu42 申请加入(请备注"zwplayer")

  4. 4、进度条预览图、字幕、章节标记针对的是测试视频,使用时需要替换为实际的进度条预览图、字幕、章节标记。

4. 示例代码

示例代码仅供参考,实际使用时需要根据实际情况进行修改。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="renderer" content="webkit">
    <meta name="viewport"
          content="width=device-width,initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="x5-fullscreen" content="true">
    <meta name="full-screen" content="yes">
    <meta name="apple-mobile-web-app-capable" content="yes"/>
    <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
    <meta name="format-detection" content="telephone=no">
    <title>综合演示</title>
    <script type="text/javascript" charset="utf-8" src="https://cdn.zwplayer.cn/v3/zwplayer/zwplayer.js"></script>
    <style>
        html, body {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }

        .player-wrap {
            position: relative;
            padding: 20px;
            width: 80%;
            margin-left: auto;
            margin-right: auto;
            min-width: 1024px;
        }

        .vxplayer {
            width: 1024px;
            height: 576px;
            margin: 0 auto;
            background-color: #222;
        }

        .vxplayer-toolbar {
            height: 40px;
            border: 1px solid #c0c0c0;
            margin-top: 20px;
            width: 100%;
            margin-left: auto;
            margin-right: auto;
            padding: 6px 10px;
            box-sizing: border-box;
            position: relative;
        }

        .vxplayer-toolbar .btn {
            border: 1px solid #a0a0a0;
            border-radius: 5px;
            min-width: 60px;
            height: 26px;
            box-sizing: border-box;
            margin: 0 5px;
            float: left;
        }

        .vxplayer-toolbar .btn:hover {
            background: #b8e1ee;
            border-color: #89baf2;
            color: #003566;
        }

        .vxplayer-toolbar .btn:hover {
            background: #83aab7;
            color: #016789;
            border-color: #2c5c81;
        }

        .url-inputbox {
            height: 26px;
            display: inline-block;
            padding: 0px 10px;
            float: left;
            font-size: 14px;
        }

        .url-inputbox .label {
            display: inline-block;
            width: 60px;
            height: 26px;
            line-height: 26px;
            padding-right: 6px;
            text-align: right;
        }

        .url-inputbox input[type="text"] {
            height: 26px;
            width: 500px;
            border: 1px solid #ccc;
            border-radius: 3px;
            line-height: 22px;
            box-sizing: border-box;
            padding-left: 6px;
            padding-right: 6px;
        }

        .opt-panel {
            width: 160px;
            float: left;
            padding: 3px 5px;
        }

        .time-info {
            padding: 10px;
            line-height: 20px;
        }

        .time-info .time-item {
            display: inline-block;
            min-width: 100px;
            padding: 0 5px;
        }

        .time-info .time-item SPAN.time-value {
            display: inline-block;
            padding-left: 6px;
            width: 120px;
            font-weight: 600;
        }

        .vxplayer-toolbar.danmubar {
            height: 48px;
            background-color: #474343;
            padding-left: 200px;
            margin-top: 0;
            border-top: 0;
            border-color: #000;
        }

        .popup_box {
            position: absolute;
            width: 800px;
            height: 300px;
            left: 100px;
            bottom: 0px;
            padding: 6px;
            background-color: #f0f0f0;
            border: 1px solid #ccc;
            display: none;
            z-index: 10000;
        }

        .popup_box .m-urls-box {
            display: block;
            width: 100%;
            height: 260px;
            border-radius: 5px;
            box-sizing: border-box;
            padding: 6px;
            white-space: nowrap;
        }

        .popup_box .popup-btoolbar {
            overflow: hidden;
            padding: 8px 0;
        }

        .cbx {
            height: 24px;
            border: 1px solid #888;
            border-radius: 3px;
            float: left;
        }

        .current-time-view {

        }

    </style>

    <script language="javascript">

        var thumbnails = {
            "url": "https://cdn.zwplayer.cn/media/b44c43c90be3521bc352aad1e80f9cd0_thumb.jpg",
            "width": 160,
            "height": 90,
            "row": 9,
            "col": 9,
            "total": 74
        };

        function formatTimeShortWithMs(timestamp) {
            // 精确到毫秒的简短格式:HH:MM:SS.mmm 使用本地时间
            var date = new Date(timestamp);
            var hours = date.getHours();
            var minutes = date.getMinutes();
            var seconds = date.getSeconds();
            var milliseconds = date.getMilliseconds();

            seconds = seconds % 60;
            minutes = minutes % 60;
            hours = hours % 24;

            return [
                hours.toString().padStart(2, '0'),
                minutes.toString().padStart(2, '0'),
                seconds.toString().padStart(2, '0')
            ].join(':') + '.' + milliseconds.toString().padStart(3, '0');
        }

        function onOpenUrl(urlObj) {
            var url;
            var streamtype = "";

            if (urlObj) {
                url = urlObj;
            } else {
                var urlbox = document.getElementById('url-box');

                url = urlbox.value;

                if (!url) {
                    alert('Please enter url.');
                    urlbox.focus();
                    return;
                }

                streamtype = document.getElementById('stream_type_cbx').value;
            }

            var isLive = document.getElementById('isLive-flag').checked;
            var isUseFlv = document.getElementById('isUseFlv-flag').checked;

            var timer = new Date();
            var timeStart = timer.getTime();
            document.getElementById('time-start').innerHTML = formatTimeShortWithMs(timeStart);

            if (!window.zwplayer) {
                //var playerDom = document.querySelector('#player-holder');
                window.zwplayer = new ZWPlayer({
                    url: url,
                    playerElm: '#player-holder', //player 元素ID ,也可以直接的DOM对象 playerDom
                    videoElm: '#videoview',   //videoElm 元素
                    videostyle: "width:100%;height:100%;",
                    reconnect: true,
                    autoplay: true,
                    nativecontrols: false,
                    isLive: isLive,
                    useOldFlv: false,
                    useFlv: isUseFlv,
                    streamtype: streamtype,
                    // hasAudio: false,
                    xmc_url: 'https://xmc.zwplayer.cn:8138/',	//请填写实际的地址
                    controlbar: true,
                    infoButton: true,
                    speedButton: true,
                    optionButton: true,
                    snapshotButton: true,
                    chapterButton: true,
                    enableDanmu: true,
                    //poster: 'https://cdn.zwplayer.cn/media/VMAP9lxJvRpgn5sP3lV6rQ9qkzQmh5psggso3185.jpg',
                    useProgressTooltip: true,
                    fixedControlbar: true,
                    hidePlayBtn: false,
                    disablePlayBtn: false,
                    disableSeek: false,
                    disableFullscreenWin: false,
                    disablePicInPic: true,
                    disableVolumeControl: false,
                    thumbnails: thumbnails,
                    fluid: true,
                    // chapters: 'http://192.168.1.202/chapters.json?v=3',
                    muted: false,
                    onready: function () {
                        console.log("Player onready");

                    },
                    onfirstframe: function () {
                        console.log("Player onfirstframe");
                    },
                    onnetclose: function () {
                        console.log("Player onnetclose");
                    },
                    onneterror: function () {
                        console.log("Player onneterror");
                    },
                    onmediaevent: function (event) {
                        if (['play', 'pause', 'seeked', 'ended', 'error'].includes(event.type)) {
                            console.log("player video Event:", event);
                            if (event.type == 'seeked') {
                                var currentTime = event.srcElement.currentTime;
                                console.log("player currentTime:", currentTime);
                            }

                            if (event.type === 'play') {
                                var timeEnd = (new Date()).getTime();
                                var timeTotal = timeEnd - timeStart;

                                document.getElementById('time-end').innerHTML = formatTimeShortWithMs(timeEnd);
                                document.getElementById('time-total').innerHTML = timeTotal;
                            }
                        }
                    },
                    sendDanmu: function (text) {
                        //alert(text);
                        if (typeof window.ws_send === 'function') {
                            window.ws_send(text);
                        }
                    }
                });

                window.zwplayer.buildDanmuControlbar('player-dammu-controlbar');
            } else {
                window.zwplayer.play(url, isLive, false);
            }
        }

        function onClose() {
            if (window.zwplayer) {
                window.zwplayer.stop();
            }
        }

        function ondestroy() {
            if (window.zwplayer) {
                window.zwplayer.destroy();
                delete window.zwplayer;
            }
        }

        //multistream-urls multistream-urls-input
        function onMultiStreams() {
            var popupbox = document.getElementById('multistream-urls-box');
            var display = popupbox.style.display;

            display = display !== 'block' ? 'block' : 'none';
            popupbox.style.display = display;
        }

        function onGetCurrentTime() {
            if (window.zwplayer) {
                var curTime = window.zwplayer.CurrentTime;

                document.getElementById('current-time-view').innerHTML = curTime;
            }
        }

        function onMultiStreamsOpen() {
            var inputBox = document.getElementById('multistream-urls-input');
            var urlText = inputBox.value;
            urlText = urlText.trim();
            if (urlText.startsWith('{') || urlText.startsWith('[')) {
                try {
                    var urls = JSON.parse(urlText);

                    if (urls) {
                        var urlInfo = {
                            murls: urls,
                            multistream: 1
                        };

                        onOpenUrl(urlInfo);

                        document.getElementById('multistream-urls-box').style.display = 'none';
                    }
                } catch (err) {
                    console.error(err);
                }
            }
        }

        function onMultiStreamsCancel() {
            document.getElementById('multistream-urls-box').style.display = 'none';
        }

        function onload() {
            url = 'https://cdn.zwplayer.cn/media/VMAP9lxJvRpgn5sP3lV6rQ9qkzQmh5psggso3185.mp4';
            document.getElementById('url-box').value = url;
            setTimeout(function () {
                onOpenUrl();
            }, 100);

            //new VConsole();
        }

        function onSendDanmu() {
            var danmuText = document.getElementById('danmu-box').value;
            if (!danmuText)
                return;
            var danmu = {
                //outlineColor: '#f00',
                border: '1px solid #ccc',
                text: danmuText
            };

            if (window.zwplayer) {
                window.zwplayer.appendDanmu(danmu);
            }
        }

        function onDisableDanmu() {
            if (window.zwplayer) {
                window.zwplayer.setEnableDanmu(false);
            }
        }

        function onEnableDanmu() {
            if (window.zwplayer) {
                window.zwplayer.setEnableDanmu(true);
            }
        }

        function onLoadChapters() {
            if (window.zwplayer) {
                window.zwplayer.setChapters('https://cdn.zwplayer.cn/media/VMAP9lxJvRpgn5sP3lV6rQ9qkzQmh5psggso3185_chapter.json');
            }
        }

        function onLoadSubtitle() {
            if (window.zwplayer) {
                var subtitleURL_korean = 'https://cdn.zwplayer.cn/media/VMAP9lxJvRpgn5sP3lV6rQ9qkzQmh5psggtFawR3lNR7hQ2_kore.srt';
                var subtitleURL_japan = 'https://cdn.zwplayer.cn/media/VMAP9lxJvRpgn5sP3lV6rQ9qkzQmh5psggtFawR3lNR7hQ2_jpan.srt';
                window.zwplayer.addSubtitle(subtitleURL_korean, '1');
                window.zwplayer.addSubtitle(subtitleURL_japan, '2');
            }
        }

        function onRemoveSubtitle() {
            if (window.zwplayer) {
                window.zwplayer.removeSubtitle();
            }
        }

        window.channelinfo = {
            id: '001'
        };

        (function (root) {
            var wsChat = null;
            var logView = null;
            var wschat_server = "ws://10.234.1.106:3000/";  //替换为实际弹幕服务器地址
            var reconnect = false;
            var msg_queue = [];
            var force_close = false;
            var userCurrent = {};


            function chat_log(str) {
                console.log(str);
            }

            function toast(type, msg) {

            }

            root.ws_init = function chatSocketInit() {

                if (wsChat) return wsChat;
                // Connect to Web Socket.
                // Change host/port here to your own Web Socket server.
                try {
                    wsChat = new WebSocket(wschat_server);
                } catch (e) {
                    return false;
                    reconnect = false;
                }

                // Set event handlers.
                wsChat.onopen = function () {
                    chat_log("wsChat onopen");

                    if (window.enableBalance == '1' && !window.mediaserver) {
                        root.ws_getmediaserver();
                    }

                    window.setTimeout(function () {
                        delete userCurrent.loginChat;
                        if (!wsChat) return;
                        wsChat.send('{type:"hello"}');

                        if (reconnect) {
                            toast('showToast', {
                                text: '与互动服务器的重新建立连接成功。',
                                sticky: false,
                                stayTime: 3000,
                                position: 'top-center',
                                type: 'notice'
                            });
                            reconnect = false;
                            if (msg_queue['userlogin']) {
                                wsChat.send(msg_queue['userlogin']);
                                delete msg_queue['userlogin'];
                            }
                        }
                    }, 40);
                };


                wsChat.onmessage = function (e) {
                    // e.data contains received string.
                    chat_log("wsChat onmessage: " + e.data);

                    if (e.data.length > 0) {
                        if (e.data.charAt(0) === '{') {
                            var msgContent;
                            var msgObj = JSON.parse(e.data);

                            if (typeof (msgObj) === 'object') {
                                if (msgObj.text)
                                    msgContent = msgObj.text;
                                else
                                    msgContent = '';

                                if (msgObj.type === 'danmu') {
                                    if (window.zwplayer) {
                                        if (msgContent == '') return;
                                        // msgObj.text = msgContent;
                                        window.zwplayer.appendDanmu(msgObj);
                                    }
                                } else if (msgObj.type === 'hello') {
                                    window.joinRoomOk = true;
                                    //获得授予的UID
                                    window.current_uid = msgObj.uid;
                                    var roomname = 'videoroom_' + window.channelinfo.id;
                                    window.ws_send('{"type":"join","room":"' + roomname + '"}');
                                } else if (msgObj.type === 'login') {
                                    if (!msgObj.result || msgObj.result != 'success') {
                                        toast('showNoticeToast', '登录到互动服务器返回不成功。<br/>可能影响聊天互动!');
                                    } else {
                                        userCurrent.loginChat = true;
                                    }
                                } else if (msgObj.type === 'logout') {
                                    //用户自己登出的回馈
                                    delete userCurrent.loginChat;
                                } else if (msgObj.type === 'event') {
                                    if (msgObj.event === 'joinroom') {
                                        //别的用户与自己连接到聊天服务器
                                        if (msgObj.uid) {
                                            if (msgObj.uid === window.current_uid) {
                                                userCurrent.joinroom = true;
                                            }
                                        }
                                    } else if (msgObj.event === 'leaveroom' || msgObj.event === 'exitroom') {
                                        //别的用户离开聊天服务器
                                        if (msgObj.uid) {
                                            if (msgObj.uid === window.current_uid) {
                                                userCurrent.joinroom = false;
                                            }
                                        }
                                    } else if (msgObj.event === 'login') {
                                        //别的用户连接到聊天服务器
                                        if (msgObj.uid) {

                                        }
                                    } else if (msgObj.event === 'logout') {
                                        //别的用户离开聊天服务器
                                        if (msgObj.uid) {

                                        }
                                    }
                                } else if (msgObj.type == 'userlist') {
                                    //连接到聊天服务器后服务器马上推送在线用户列表,该列表不包括自己
                                    if (msgObj.users.length > 1) {

                                    }
                                } else if (msgObj.type === 'setuserid') {
                                    //连接建立后将收到这个事件
                                    window.current_uid = msgObj.uid;
                                    userCurrent.userid = msgObj.uid;
                                }
                            }
                        }
                    }
                };

                wsChat.onclose = function () {
                    chat_log("wsChat onclose");
                    wsChat = null;
                    toast('showToast', {
                        text: '与互动服务器的连接已经断开。',
                        sticky: false,
                        stayTime: 3000,
                        position: 'top-center',
                        type: 'notice'
                    });
                    if (force_close) {


                    } else if (!reconnect) { //当前不是重连状态,则尝试重连
                        reconnect = true; //设置为正在重连状态
                        var on_reconnect = function () {
                            if (force_close) return;

                            wschat = root.wschat = root.ws_init();
                            if (!wschat) {
                                reconnect = true;
                                window.setTimeout(on_reconnect, 10000);
                            }
                        }
                        window.setTimeout(on_reconnect, 10000);
                    }
                };

                wsChat.onerror = function () {

                    chat_log("wsChat onerror");
                    wsChat = null;
                };

                return wsChat;
            }

            root.ws_send = function wsChatSend(data) {
                chat_log("wsChat send: " + data);

                if (wsChat) {
                    wsChat.send(data);
                    return true;
                } else {
                    toast('showToast', {
                        text: '聊天交互服务没有连接成功或已经中断!<br/>正在尝试重连,请稍候再试...',
                        sticky: false,
                        stayTime: 3000,
                        position: 'top-center',
                        type: 'warning'
                    });

                    reconnect = true;
                    wschat = root.wschat = root.ws_init();

                    return false;
                }
            }

            root.ws_queue = function wsQueue(type, msg) {
                msg_queue[type] = msg;
            }

            root.ws_close = function wsChatClose() {
                if (wsChat) {
                    force_close = true;
                    wsChat.close();
                    wsChat = null;
                } else {

                }
            }

            root.wschat = wsChat;
        })(window);

        window.ws_init();

    </script>
</head>

<body>
<div class="player-wrap">

    <div class="vxplayer" id="player-holder">
        <!-- video id="videoview"> </video //-->
    </div>
    <div class="vxplayer-toolbar danmubar" id="player-dammu-controlbar"></div>
    <div class="vxplayer-toolbar" id="player-toolbar">
        <button class="btn" onclick="onOpenUrl();">Open</button>
        <button class="btn" onclick="onClose();">Close</button>
        <button class="btn" onclick="ondestroy();">Destroy</button>

        <div class="url-inputbox">
            <span class="label">URL:</span>
            <input type="text" id="url-box"
                   value="https://cdn.zwplayer.cn/media/VMAP9lxJvRpgn5sP3lV6rQ9qkzQmh5psggso3185.mp4">
        </div>
        <div class="opt-panel">
            <input type="checkbox" id="isLive-flag" value="1">
            <label for="isLive-flag">LIVE</label>

            <input type="checkbox" id="isUseFlv-flag" value="1" title="use flv player">
            <label for="isUseFlv-flag">Use Flv</label>
        </div>

        <div class="popup_box" id="multistream-urls-box">
            <textarea class="m-urls-box" id="multistream-urls-input"></textarea>
            <div class="popup-btoolbar">
                <button class="btn" onclick="onMultiStreamsOpen();">Open</button>
                <button class="btn" onclick="onMultiStreamsCancel();">Cancel</button>
            </div>
        </div>
    </div>
    <div class="vxplayer-toolbar" id="player-dammubar">
        <div class="url-inputbox">
            <span class="label">DANMU:</span>
            <input type="text" id="danmu-box" value="">
        </div>
        <button class="btn" onclick="onSendDanmu();">Send</button>
        <button class="btn" onclick="onEnableDanmu();">Enable Danmu</button>
        <button class="btn" onclick="onDisableDanmu();">Disable Danmu</button>
    </div>

    <div class="vxplayer-toolbar" id="player-other">
        <button class="btn" onclick="onLoadChapters();">Load Chapters</button>
        <button class="btn" onclick="onLoadSubtitle();">Load Subtitle</button>
        <button class="btn" onclick="onRemoveSubtitle();">Remove Subtitle</button>
        <button class="btn" onclick="onMultiStreams();">MStreams</button>

        <select class="cbx" id="stream_type_cbx">
            <option value="">stream_type No specified</option>
            <option value="httpflv">httpflv</option>
            <option value="hls">hls</option>
            <option value="dash">dash</option>
            <option value="webrtc">webrtc</option>
            <option value="mpegts">mpegts</option>
        </select>
        <button class="btn" onclick="onGetCurrentTime();">CurrentTime</button>
        <span id="current-time-view" class="current-time-view"></span>
    </div>
    <div class="vxplayer-toolbar time-info">
        <div class="time-item"><span>start:</span><span class="time-value" id="time-start"></span></div>
        <div class="time-item"><span>end:</span><span class="time-value" id="time-end"></span></div>
        <div class="time-item"><span>diffTime:</span><span class="time-value" id="time-total"></span>ms</div>
    </div>
    <div><span>注意:建议使用chrome浏览器,如果遇到跨域问题不能播放,可加--disable-web-security 参数启动chrome浏览器。</span>
    </div>
</div>
</body>
</html>
目录导航