zoukankan      html  css  js  c++  java
  • vue+flv.js 实时播放单个和多个视频流dome

    安装vlc 地址https://www.videolan.org/vlc/ 

    打开网络串流测试视频流是否可用


    安装 npm install --save flv.js

    1.单个flv.js dome

    <template>
        <div>
            <video class="demo-video" ref="player" muted autoplay></video>
        </div>
    </template>
    <script>
    import flvjs from "flv.js";
    export default {
        data () {
            return {
                player: null
            }
        },
        mounted () {
            if (flvjs.isSupported()) {
                let video = this.$refs.player;
                if (video) {
                    this.player = flvjs.createPlayer({
                        type: "flv",
                        isLive: true,
                        url: `http://1011.hlsplay.aodianyun.com/demo/game.flv`
                    });
                    this.player.attachMediaElement(video);
                    try {
                        this.player.load();
                        this.player.play();
                    } catch (error) {
                        console.log(error);
                    };
                }
            }
        },
        beforeDestroy () {
            this.player.destory();
        }
    }
    </script>
    <style>
        .demo-video {
            max- 880px; 
            max-height: 660px;
        }
    </style>


    原文链接:https://blog.csdn.net/weixin_42536639/article/details/102870788

    2.点击列表显示相应flv流 (注:浏览器页面最多显示6个flv流 )

    功能:点击右边菜单出现实时监控画面,页面有四个窗体,每个窗体播放不同的视频,当四个窗体都在播放时,点击下一个会依次替换每个窗体,随机点四个页面会出现对应的实时视频

    这段代码解决了

    开发问题1:离开页面视频会暂停(就没有实时性)
    开发问题2:页面会疯狂报错(不影响功能,但是浏览器受不了)
    开发问题3:怎么当四个窗体都在播放时,点击下一个会依次替换每个窗体
    开发问题4:怎么断掉上一个视频的推流(视频会卡顿)
    开发问题5:怎么断开重新连接

    <template>
      <div class="videobox">
        <div class="videolist">
          <div class="search">
            <ul>
              <li
                v-for="(item, index) in rtsplist"
                :key="index"
                @click="clickhandleitem(item, index)"
              >
                <i class="el-icon-video-camera-solid"></i>
                列表{{index}}
              </li>
            </ul>
          </div>
        </div>
        <div class="video">
          <video
            autoplay
            muted
            width="400px"
            height="300px"
            v-for="(i,index) in 4"
            :id="'videoElement' + i"
            :key="index"
          ></video>
        </div>
      </div>
    </template>
    
    <script>
    import flvjs from "flv.js";
    export default {
      data() {
        return {
           rtsplist: [
            {
              rtsp: "http://1011.hlsplay.aodianyun.com/demo/game.flv",
              player: null
            },
            {
              rtsp: "http://1011.hlsplay.aodianyun.com/demo/game.flv",
              player: null
            },
            
            {
              rtsp: "http://1011.hlsplay.aodianyun.com/demo/game.flv",
              player: null
            },
            {
              rtsp: "http://1011.hlsplay.aodianyun.com/demo/game.flv",
              player: null
            },
            {
              rtsp: "http://1011.hlsplay.aodianyun.com/demo/game.flv",
              player: null
            },
            {
              rtsp: "http://1011.hlsplay.aodianyun.com/demo/game.flv",
              player: null
            },
            
            {
              rtsp: "http://1011.hlsplay.aodianyun.com/demo/game.flv",
              player: null
            },
            {
              rtsp: "http://1011.hlsplay.aodianyun.com/demo/game.flv",
              player: null
            },
            
          ],
          flvPlayer: null,
          inputvalue: "",
          devicename: "60",
          url: "",
          list: [],
          count: 1, // 当前点击标识
          flvPlayerList: [],
          datalist:[]
        };
      },
      methods: {
        clickhandleitem(data, index) {
          let ip = data.ipAddress;
          let admin = data.videoname;
          let password = data.videopas;
    
          this.url =this.rtsplist[index].rtsp
          console.log(this.flvPlayerList,'flvPlayerList')
          if (this.flvPlayerList.length > 3) {
            this.destoryVideo(this.flvPlayerList[0]);
            this.flvPlayerList.shift();
          }
          this.createVideo();
          console.log(index)
          this.count > 3 ? (this.count = 1) : this.count++;
          console.log(this.count)
        },
        createVideo() {
          if (flvjs.isSupported()) {
            var videoElement = document.getElementById("videoElement" + this.count);
            this.flvPlayer = flvjs.createPlayer(
              {
                type: "flv",
                isLive: true,
                hasAudio: false,
                url: this.url
              },
              {
                enableWorker: false, //不启用分离线程
                enableStashBuffer: false, //关闭IO隐藏缓冲区
                reuseRedirectedURL: true, //重用301/302重定向url,用于随后的请求,如查找、重新连接等。
                autoCleanupSourceBuffer: true //自动清除缓存
              }
            );
    
            this.flvPlayer.attachMediaElement(videoElement);
            // this.flvPlayer.load();
    
            if (this.url !== "" && this.url !== null) {
              this.flvPlayer.load();
              this.flvPlayer.play();
            }
          }
    
          //定时方法是为了用户离开页面视频是实时播放的,暂停按钮无用
          setInterval(function() {
            // console.log(videoElement.buffered,"idididid");
            if (videoElement.buffered.length > 0) {
              const end = videoElement.buffered.end(0); // 视频结尾时间
              const current = videoElement.currentTime; //  视频当前时间
              const diff = end - current; // 相差时间
              // console.log(diff);
              const diffCritical = 4; // 这里设定了超过4秒以上就进行跳转
              const diffSpeedUp = 1; // 这里设置了超过1秒以上则进行视频加速播放
              const maxPlaybackRate = 4; // 自定义设置允许的最大播放速度
              let playbackRate = 1.0; // 播放速度
              if (diff > diffCritical) {
                //  this.flvPlayer.load();
                // console.log("相差超过4秒,进行跳转");
                videoElement.currentTime = end - 1.5;
                playbackRate = Math.max(1, Math.min(diffCritical, 16));
              } else if (diff > diffSpeedUp) {
                // console.log("相差超过1秒,进行加速");
                playbackRate = Math.max(1, Math.min(diff, maxPlaybackRate, 16));
              }
              videoElement.playbackRate = playbackRate;
              if (videoElement.paused) {
                videoElement.play();
              }
            }
            //  if (videoElement.buffered.length) {
            //   let end = this.flvPlayer.buffered.end(0);//获取当前buffered值
            //   let diff = end - this.flvPlayer.currentTime;//获取buffered与currentTime的差值
            //   if (diff >= 0.5) {//如果差值大于等于0.5 手动跳帧 这里可根据自身需求来定
            //     this.flvPlayer.currentTime = this.flvPlayer.buffered.end(0);//手动跳帧
            //  }
            // }
          }, 1000);
    
          this.flvPlayer.on(flvjs.Events.ERROR, (errType, errDetail) => {
            // alert("网络波动,正在尝试连接中...");
            if (this.flvPlayer) {
              this.reloadVideo(this.flvPlayer);
            }
            // errType是 NetworkError时,对应errDetail有:Exception、HttpStatusCodeInvalid、ConnectingTimeout、EarlyEof、UnrecoverableEarlyEof
            // errType是 MediaError时,对应errDetail是MediaMSEError   或MEDIA_SOURCE_ENDED
          });
          this.flvPlayerList.push(this.flvPlayer);
        },
    
        reloadVideo(flvPlayer) {
          this.destoryVideo(flvPlayer);
          this.createVideo();
        },
        destoryVideo(flvPlayer) {
          flvPlayer.pause();
          flvPlayer.unload();
          flvPlayer.detachMediaElement();
          flvPlayer.destroy();
          flvPlayer = null;
        },
      }
    };
    </script>
    
    <style lang="scss" scoped>
    .videobox {
      display: flex;
      /* justify-content: space-between; */
      /* flex-wrap: wrap; */
    }
    .videolist {
       550px;
      height: 906px;
      display: flex;
      .search {
        margin-left: 50px;
        .el-input {
           300px;
          margin-top: 20px;
        }
        ul {
           100%;
          height: 777px;
          overflow: hidden;
          overflow-y: auto;
          list-style: none;
          li {
            padding: 7px;
            margin: 1px 0;
            text-decoration: none;
            white-space: nowrap;
            font-size: 14px;
            cursor: pointer;
            &:hover {
              background: #fff;
            }
            .el-icon-video-camera-solid {
              font-size: 16px;
              color: #67c23a;
            }
          }
        }
      }
    }
    .video {
      display: flex;
      flex-wrap: wrap;
       100%;
      justify-content: space-evenly;
      video {
        object-fit: contain;
         600px;
        height: 390px;
      }
    }
    </style>

    原文链接:https://blog.csdn.net/weixin_45906632/article/details/115031633

    遇到的问题

    第一种报错情况:谷歌浏览器控制台出现的报错
    使用报错如下:Failed to read the ‘buffered’ property from ‘SourceBuffer’: This SourceBuffer has been removed from the parent media source.

    这种错误提示一般是在flv源发生异常中断的时候产生的。错误提示大多数都在 mse-controller.js 这个模块中。
    解决办法:在 mse-controller.js中(flv.js/src/core/mse-controller.js),appendMediaSegment()、_needCleanupSourceBuffer()这些方法的入口处调用检查以下MediaSource的合法性。

    if (!this._mediaSource || this._mediaSource.readyState !== 'open') {
              return;
          }

    原文链接:https://blog.csdn.net/xyy1234567891/article/details/110005429

  • 相关阅读:
    【前端知识体系-JS相关】组件化和React
    【前端知识体系-JS相关】虚拟DOM和Diff算法
    【前端知识体系-JS相关】ES6专题系列总结
    【前端开发环境】前端使用GIT管理代码仓库需要掌握的几个必备技巧和知识点总结
    webpack代码分离CommonsChunkPlugin插件的使用(防止重复)
    webpack管理输出
    webpack管理资源(loader操作)
    window启动webpack打包的三种方法
    echarts地图map城市间如何连线
    echarts水球图编写
  • 原文地址:https://www.cnblogs.com/minghan/p/14923282.html
Copyright © 2011-2022 走看看