详解Vue实现直播功能

最近公司刚好在做直播,那么今天就记录一下遇到的坑,公司服务器用的亚马逊aws,所以直接看官方的api就可以了,aws官方地址aws直播api
先看下具体的实现后的效果图把

按照网上成熟的方法,使用的是video.js,然后aws做了一层封装,那么我们直接拿来使用把,这里使用vue版本的vue-video-player

先安装下相关的包

npm install vue-video-player --save

在main.js引入vue-video-player

// 第一个是videoJs的样式,后一个是vue-video-player的样式,因为考虑到我其他业务组件可能也会用到视频播放,所以就放在了main.js内
require('video.js/dist/video-js.css')
require('vue-video-player/src/custom-theme.css')
/*导入视频播放组件*/
import VideoPlayer from 'vue-video-player'
Vue.use(VideoPlayer)

导入组件,修改配置参数

          <video-player
            class="video-player vjs-custom-skin"
            ref="videoPlayer"
            :options="playerOptions"
            @play="onPlayerPlay($event)"
            @pause="onPlayerPause($event)"
            @statechanged="playerStateChanged($event)"
          ></video-player>

修改参数,添加src

     playerOptions: {
       playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
       autoplay: false, //如果true,浏览器准备好时开始回放。
       controls: true, //控制条
       preload: "auto", //视频预加载
       muted: true, //默认情况下将会消除任何音频。
       loop: false, //导致视频一结束就重新开始。
       language: "zh-CN",
       aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
       fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
       sources: [
         {
           withCredentials: false,
           type: "application/x-mpegURL",
           //src: this.liveSrc
           src:
             "https://50f5175980ea.us-east-1.playback.live-video.net/api/video/v1/us-east-1.003054160756.channel.bSt8OCsmBtFq.m3u8"
         }
       ],
       poster: this.image, //你的封面地址
       //width: 200 || document.documentElement.clientWidth,
       notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。
       controlBar: {
         timeDivider: true, // 当前时间和持续时间的分隔符
         durationDisplay: true, // 显示持续时间
         remainingTimeDisplay: false, // 是否显示剩余时间功能
         fullscreenToggle: true // 是否显示全屏按钮
       }
     },

注意要先测试直播源可以成功播放才可以,否则就会报下这些错误

那么我们先按照官方的搭建一个本地的直播源测试吧

先搭建html界面,注意要引入相关的js库和文件,我这里用hbuilder,因为用的比较顺手,而且预览模式类似于开了一个端口,通过get方式的方法,返回了一个本地服务,而不是直接本地双击打开html文件,访问静态文件哦~~~~

<!doctype html>
<html lang="en">
<head>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.11.4/video-js.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.11.4/video.min.js"></script>
    <script src="https://player.live-video.net/1.4.0/amazon-ivs-videojs-tech.min.js"></script>
</head>
<body>
    <div class="video-container">
        <video id="amazon-ivs-videojs" class="video-js vjs-4-3 vjs-big-play-centered" controls autoplay playsinline></video>
    </div>
    <style>
        body {
            margin: 0;
        }
        .video-container {
            width: 640px;
            height: 480px;
            margin: 15px;
        }
    </style>
    <script>
        (function play() {
            // Get playback URL from Amazon IVS API
            //var PLAYBACK_URL = 'https://50f5175980ea.us-east-1.playback.live-video.net/api/video/v1/us-east-1.003054160756.channel.bSt8OCsmBtFq.m3u8';
            var PLAYBACK_URL = 'https://50f5175980ea.us-east-1.playback.live-video.net/api/video/v1/us-east-1.003054160756.channel.bSt8OCsmBtFq.m3u8'
            // Register Amazon IVS as playback technology for Video.js
            registerIVSTech(videojs);
            // Initialize player
            var player = videojs('amazon-ivs-videojs', {
               techOrder: ["AmazonIVS"]
            }, () => {
               console.log('Player is ready to use!');
               // Play stream
               player.src(PLAYBACK_URL);
            });
        })();
    </script>
</body>
</html>

通过端口访问,

后来发现通过本地静态文件,也可以实现在线直播源播放

ps:如果不想自己搭建本机服务测试,也可以直接使用awd提供的在线测试
https://replit.com/@changdong0524/amazon-ivs-player-web-sample#samples/common/form-control.ts,但是要自己注册账号哦
大概就是下面这样子哦

大家自己去摸索一下就会了,修改input.value为直播源地址,然后在右边shell控制台启动就可以了

npm  install && npm  run  start

效果如下,是一模一样的

load这里的地址换成你自己的直播源m3u8格式就好了,我这里是已经搭建好的在线直播源

直播源没问题后,接下来就直接继续写项目代码

  <template>
    <div class='demo'>
      <video-player class="video-player vjs-custom-skin"
        ref="videoPlayer"
        :playsinline="true"
        :options="playerOptions"
        @play="onPlayerPlay($event)"
        @pause="onPlayerPause($event)"
        @ended="onPlayerEnded($event)"
        @waiting="onPlayerWaiting($event)"
        @playing="onPlayerPlaying($event)"
        @loadeddata="onPlayerLoadeddata($event)"
        @timeupdate="onPlayerTimeupdate($event)"
        @canplay="onPlayerCanplay($event)"
        @canplaythrough="onPlayerCanplaythrough($event)"
        @statechanged="playerStateChanged($event)"
        @ready="playerReadied"
      >
      </video-player>
    </div>
  </template>

  <script>
    export default {
      methods: {
        // 播放回调
        onPlayerPlay(player) {
          console.log('player play!', player)
        },

        // 暂停回调
        onPlayerPause(player) {
          console.log('player pause!', player)
        },

        // 视频播完回调
        onPlayerEnded($event) {
          console.log(player)
        },

        // DOM元素上的readyState更改导致播放停止
        onPlayerWaiting($event) {
          console.log(player)
        },

        // 已开始播放回调
        onPlayerPlaying($event) {
          console.log(player)
        },

        // 当播放器在当前播放位置下载数据时触发
        onPlayerLoadeddata($event) {
          console.log(player)
        },

        // 当前播放位置发生变化时触发。
        onPlayerTimeupdate($event) {
          console.log(player)
        },

        //媒体的readyState为HAVE_FUTURE_DATA或更高
        onPlayerCanplay(player) {
          // console.log('player Canplay!', player)
        },

        //媒体的readyState为HAVE_ENOUGH_DATA或更高。这意味着可以在不缓冲的情况下播放整个媒体文件。
        onPlayerCanplaythrough(player) {
          // console.log('player Canplaythrough!', player)
        },

        //播放状态改变回调
        playerStateChanged(playerCurrentState) {
          console.log('player current update state', playerCurrentState)
        },

        //将侦听器绑定到组件的就绪状态。与事件监听器的不同之处在于,如果ready事件已经发生,它将立即触发该函数。。
        playerReadied(player) {
          console.log('example player 1 readied', player);
        }

      },
    }
 </script>

定义相关的监听函数,可以根据自己需要加上,常用的有下面几个

    onPlayerPlay(player) {
      console.log("onPlayerPlay", player);
    },
    onPlayerPause(player) {
      console.log("onPlayerPause", player);
    },
    playerStateChanged(player) {
      console.log("playerStateChanged", player);
    },

然后启动服务

npm  run start

发现报错,无法找到相关的视频,于是发现缺少相关的库,还得加上aws的库才可以
在整个项目的index.html中加入下面的库支持文件

  <link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.11.4/video-js.css" rel="stylesheet">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.11.4/video.min.js"></script>
  <script src="https://player.live-video.net/1.4.0/amazon-ivs-videojs-tech.min.js"></script>

最后完整效果就出来了

注意事项:
video-player标签的class必须设置成“video-player vjs-custom-skin”,你引入的样式才能起作用。 增加hls的支持。支持流媒体m3u8g等等格式播放。

增加hls.js支持,故此要安装依赖,如下:

npm install --save videojs-contrib-hls

这里提供下aws的官方仓库啊,需要自取哦
https://github.com/aws-samples

补充一下:如果直接在页面中实现的话,可能无法直接播放,会报错无法播放视频,我猜测可能有2个原因,见截图

1:异步获取后台返回的拉流地址的时候,需要一定的时间,这个时间直播组件已经初始化完毕,但是还没有获取到直播源地址,所以会报错找不到直播地址
2:直播组件也有自己一整套完整的生命周期,我们可以检测不同的生命周期,然后把直播源地址,在请求完毕后放入合适的时间,直播组件会一直请求这个直播地址,从而实现在线直播
这里我为了偷懒,暂时没有那么多时间去研究一下,等空了会去仔细研究一下,我是把他抽离出一个单组的子组件,通过props来实现地址的传递


效果一样一样的,也可以方便其他组件调用

最后为了方便管理,双手奉上最后的全部代码
start
1:main.js

// 第一个是videoJs的样式,后一个是vue-video-player的样式,因为考虑到我其他业务组件可能也会用到视频播放,所以就放在了main.js内
require('video.js/dist/video-js.css')
require('vue-video-player/src/custom-theme.css')
/*导入视频播放组件*/
import VideoPlayer from 'vue-video-player'
Vue.use(VideoPlayer)

2:videoPlayer.vue

<template>
  <video-player
    class="video-player vjs-custom-skin"
    ref="videoPlayer"
    :options="playerOptions"
    @play="onPlayerPlay($event)"
    @pause="onPlayerPause($event)"
    @statechanged="playerStateChanged($event)"
  ></video-player>
</template>

<script >
//import { registerIVSTech } from "amazon-ivs-player";
export default {
  name: "",
  props: ["src", "image"],
  data() {
    return {
      // liveSrc:
      //   "https://50f5175980ea.us-east-1.playback.live-video.net/api/video/v1/us-east-1.003054160756.channel.bSt8OCsmBtFq.m3u8",
      playerOptions: {
        playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
        autoplay: false, //如果true,浏览器准备好时开始回放。
        controls: true, //控制条
        preload: "auto", //视频预加载
        muted: false, //默认情况下将会消除任何音频。
        loop: false, //导致视频一结束就重新开始。
        language: "zh-CN",
        aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
        fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
        sources: [
          {
            withCredentials: false,
            type: "application/x-mpegURL",
            src: this.src
            //  "https://50f5175980ea.us-east-1.playback.live-video.net/api/video/v1/us-east-1.003054160756.channel.bSt8OCsmBtFq.m3u8"
          }
        ],
        poster: this.image, //你的封面地址
        //width: 200 || document.documentElement.clientWidth,
        notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。
        controlBar: {
          timeDivider: true, // 当前时间和持续时间的分隔符
          durationDisplay: true, // 显示持续时间
          remainingTimeDisplay: false, // 是否显示剩余时间功能
          fullscreenToggle: true // 是否显示全屏按钮
        }
      }
    };
  },
  // livePlays() {
  //   this.playerOptions.sources[0].src = this.liveSrc;
  //   var obj = {};
  //   obj.withCredentials = false;
  //   obj.type = "application/x-mpegURL";
  //   obj.src = this.pullUrl;
  //   this.playerOptions.sources.append(obj);
  // },
  computed: {
    player() {
      return this.$refs.videoPlayer.player;
    }
  },
  computed: {
    player() {
      return this.$refs.videoPlayer.player;
    }
  },
  methods: {
    onPlayerPlay(player) {
      console.log("onPlayerPlay", player);
    },
    onPlayerPause(player) {
      console.log("onPlayerPause", player);
    },
    playerStateChanged(player) {
      console.log("playerStateChanged", player);
    }
  }
};
</script>

3:detail.vue 父组件

<template>
  <d2-container>
    <div>
      <div class="webTitle">直播管理 > 大型直播 > 详情</div>
      <el-table :data="list" border stripe>
        <el-table-column align="center" label="直播ID">
          <template slot-scope="scope">
            <span>{{ scope.row.id }}</span>
          </template>
        </el-table-column>
        <el-table-column align="center" label="直播标题">
          <template slot-scope="scope">
            <span>{{ scope.row.title }}</span>
          </template>
        </el-table-column>
        <el-table-column align="center" label="账号">
          <template slot-scope="scope">
            <span>{{ scope.row.name }}</span>
          </template>
        </el-table-column>
        <el-table-column align="center" label="直播开始时间">
          <template slot-scope="scope">
            <span>{{ scope.row.liveStart | timestampFormat }}</span>
          </template>
        </el-table-column>
        <el-table-column align="center" label="观看人数">
          <template slot-scope="scope">
            <span>{{ scope.row.watchNumber }}</span>
          </template>
        </el-table-column>
        <el-table-column align="center" label="评论数">
          <template slot-scope="scope">
            <span>{{ scope.row.reserveNumber }}</span>
          </template>
        </el-table-column>
        <el-table-column align="center" label="购票金额(GP)">
          <template slot-scope="scope">
            <span>{{scope.row.preSaleType == 1 ? scope.row.preSaleBalance*1 + scope.row.preSaleDeposit *1+ scope.row.fullPayment*1 : scope.row.fullPayment}}</span>
          </template>
        </el-table-column>
        <el-table-column align="center" label="礼物金额">
          <template slot-scope="scope">
            <span>{{ scope.row.reserveNumber }}</span>
          </template>
        </el-table-column>
      </el-table>
      <div class="playWrap">
        <div class="livePicture">
          <vueVideoPlayers :src="src" :image="image" />
        </div>
        <div class="liveCommet"></div>
      </div>
      <div class="playWrap">
        <div class="playLeft">
          <p>基本信息</p>
          <ul class="leftInfo">
            <li class="playItem">
              <span class="playTitle">分类</span>
              <span class="playContent">{{typeName}}</span>
            </li>
            <li class="playItem">
              <span class="playTitle">预售类型</span>
              <span class="playContent">{{formData.preSaleType == 1 ? "预售" :"非预售"}}</span>
            </li>
            <li class="playItem">
              <span class="playTitle">是否录播</span>
              <span class="playContent">{{formData.isRecordedBroadcast ==1 ? "录播" : "不录播"}}</span>
            </li>
            <li class="playItem">
              <span class="playTitle">演员列表</span>
              <span class="playContent">{{formData.actor}}</span>
            </li>
            <li class="playItem">
              <span class="playTitle">直播介绍</span>
              <span class="playContent">{{formData.liveIntroduce}}</span>
            </li>
          </ul>
          <p>预售信息</p>
          <ul class="leftInfo">
            <li class="playItem">
              <span class="playTitle">预售时段</span>
              <span class="playContent">
                {{formData.preSaleStart}}
                <span style="color:#333;margin:0 5px">-</span>
                {{formData.preSaleEnd}}
              </span>
            </li>
            <li class="playItem">
              <span class="playTitle">成型人数</span>
              <span class="playContent">{{formData.formingNum ? formData.formingNum : 0}}</span>
            </li>
            <li class="playItem">
              <span class="playTitle">成型状态</span>
              <span
                class="playContent"
              >{{formData.reserveNumber > formData.reserveNumber ? "已成型":"未成型" }}</span>
            </li>
          </ul>
          <p>非预售信息</p>
          <ul class="leftInfo">
            <li class="playItem">
              <span class="playTitle">售票开始时间</span>
              <span class="playContent">{{formData.ticketingStart}}</span>
            </li>
          </ul>

          <p>票价</p>
          <ul class="leftInfo">
            <li class="playItem">
              <span class="playTitle">预售定金</span>
              <span class="playContent">{{formData.preSaleDeposit ? formData.preSaleDeposit : 0}}</span>
            </li>
            <li class="playItem">
              <span class="playTitle">预售尾款</span>
              <span class="playContent">{{formData.preSaleBalance ? formData.preSaleBalance : 0}}</span>
            </li>
            <li class="playItem">
              <span class="playTitle">全款价格</span>
              <span class="playContent">{{formData.fullPayment ? formData.fullPayment : 0}}</span>
            </li>
            <li class="playItem">
              <span class="playTitle">回放价格</span>
              <span class="playContent">{{formData.playbackPrice ? formData.playbackPrice : 0}}</span>
            </li>
          </ul>
        </div>
        <div class="playRight">
          <p>图像资料</p>
          <ul class="leftInfo">
            <li class="playItem">
              <span class="playTitle">宣传视频</span>
              <span class="playContent">
                <img
                  v-if="formData.propagandaVideoUrl"
                  :src="videoPng"
                  class="playImage"
                  @click="showVideo(formData.propagandaVideoUrl,true)"
                />
                <span v-else style="color:#cfcfcf">暂无视频</span>
              </span>
            </li>
            <li class="playItem">
              <span class="playTitle">回访视频</span>
              <span class="playContent">
                <img
                  v-if="formData.recordedBroadcastUrl"
                  :src="videoPng"
                  class="playImage"
                  @click="showVideo(formData.recordedBroadcastUrl,false)"
                />
                <span v-else style="color:#cfcfcf">暂无视频</span>
              </span>
            </li>
            <li class="playItem">
              <span class="playTitle">分享海报</span>
              <span class="playContent">
                <el-image
                  class="matchImg"
                  :src="formData.shareImage"
                  :preview-src-list="[formData.shareImage]"
                />
              </span>
            </li>
            <li class="playItem">
              <span class="playTitle">封面图片</span>
              <span class="playContent">
                <el-image
                  class="matchImg"
                  v-for="(item,index)  in  JSON.parse(formData.coverImage)"
                  :src="item"
                  :key="index"
                  :preview-src-list="[item]"
                />
              </span>
            </li>
          </ul>
          <!-- <p>图像资料</p>
          <ul class="leftInfo"></ul>-->
        </div>
      </div>
    </div>
    <el-button @click="backPage">返回</el-button>
    <el-dialog title="查看" :visible.sync="videoVisible" width="850px">
      <div v-if="video">
        <video :src="tempSrc" controls="controls" width="800" height="600">您的浏览器不支持 video 标签。</video>
      </div>
      <div v-else>
        <vueVideoPlayers :src="tempSrc" :image="image" />
      </div>
    </el-dialog>
  </d2-container>
</template>

<script >
import { getLiveDetail, getLiveSellDetail } from "@/api/3d/liveApi";
import videoPng from "@/assets/img/video.jpg";
import { timestampFormat } from "@/common/filters";
//import { registerIVSTech } from "amazon-ivs-player";
import vueVideoPlayers from "./videoPlayer";

export default {
  name: "",
  data() {
    return {
      src: "", //直播源视频
      image: "",
      videoPng: videoPng,
      video: true,
      videoVisible: false,
      // videoSrc: "",   //宣传视频
      // recordedBroadcastUrl:'',   //回放视频
      tempSrc: "",
      list: [],
      id: "",
      typeName: "",
      pullUrl: "",
      formData: {
        id: "",
        pullUrl: "",
        pushUrl: "",
        title: "",
        liveIntroduce: "",
        actor: "",
        typeId: "",
        isRecordedBroadcast: 2,
        coverImage: "",
        propagandaVideoUrl: "",
        formingNum: "",
        preSaleDeposit: "", //预售定金价格
        preSaleBalance: "", //预售尾款价格
        fullPayment: "", //全款价格
        playbackPrice: "", //回放价格
        preSale: [], //预售时间
        preSaleStart: "",
        preSaleEnd: "",
        liveStart: "", //直播开始时间
        isSpeak: 1,
        priority: "",
        shareImage: ""
      }
    };
  },
  created() {
    this.getLiveSell();
    this.getData();
  },
  mounted() {},
  components: {
    vueVideoPlayers
  },
  methods: {
    backPage() {
      this.$router.push("/liveMange/largeBrand");
    },
    //售票情况
    getLiveSell() {
      var id = this.$route.params.id;
      getLiveSellDetail(id).then(res => {
        const result = res.data;
      });
    },
    //弹框打开看视频
    showVideo(playSrc, mark) {
      this.videoVisible = true;
      this.video = mark;
      this.tempSrc = playSrc;
    },
    getData() {
      var id = this.$route.params.id;
      this.id = id;
      //var  localMatchTypeId=localStorage.getItem('matchTypeId')
      //var  localPriority = localStorage.getItem('priority')
      // var data = { id, page: 1, limit: 10 };
      getLiveDetail(id).then(res => {
        const result = res.data;
        //没有分类ID取本地
        // if(!result.matchTypeId){
        //   result.matchTypeId = localMatchTypeId
        // }
        // if(!result.priority){
        //   result.priority = localPriority
        // }

        this.formData = result;
        let { pullUrl, pushUrl, coverImage } = result;
        this.src = pullUrl;
        this.image = JSON.parse(coverImage)[0];
        const {
          id,
          title,
          liveStart,
          ticketingStart,
          playbackPrice,
          preSaleDeposit,
          preSaleBalance,
          fullPayment
        } = result;

        const objData = {
          id,
          title,
          name: "admin",
          liveStart,
          watchNumber: localStorage.getItem("watchNumber") | 0,
          reserveNumber: localStorage.getItem("reserveNumber") | 0,
          preSaleDeposit,
          preSaleBalance,
          fullPayment,
          ticketingStart,
          playbackPrice
        };

        this.list.push(objData);
        // this.formData.registrationStart=result.registrationStart + ''
        // this.formData.registrationEnd = result.registrationEnd + ''
        // this.formData.voteStart = result.voteStart + ''
        // this.formData.voteEnd = result.voteEnd + ''

        //投票时段
        // var preSaleStart = moment(parseInt(result.preSaleStart)).format(
        //   "YYYY-MM-DD hh:mm:ss:SSS"
        // );
        // var preSaleEnd = moment(parseInt(result.preSaleEnd)).format(
        //   "YYYY-MM-DD hh:mm:ss:SSS"
        // );
        //赛事结束时段
        // this.formData.liveStart = new Date(result.liveStart);
        //this.formData.registration.push(start)
        //this.formData.registration.push(end)
        //手动赋值
        // this.$set(this.formData, "preSale", [preSaleStart, preSaleEnd]);
        //this.$set(this.formData, "vote", [voteStart, voteEnd]);

        //日期格式化
        //预售  时间段
        this.formData.preSaleStart = result.preSaleStart
          ? timestampFormat(result.preSaleStart)
          : "";
        this.formData.preSaleEnd = result.preSaleEnd
          ? timestampFormat(result.preSaleEnd)
          : "";

        //非预售 开始售票时间
        this.formData.ticketingStart = result.ticketingStart
          ? timestampFormat(result.ticketingStart)
          : "";

        this.typeName = localStorage.getItem("typeName") || "";
      });
    }
  }
};
</script>

<style  scoped>
.playWrap {
  display: flex;
  background: #fff;
  margin-top: 20px;
}

.leftInfo {
  list-style: none;
  border: 1px solid #cfcfcf;
}
.playLeft {
  width: 48%;
  /* border: 1px  solid #f5f5f5; */
}
.playRight {
  width: 48%;
  margin-left: 2%;
}
.playItem {
  display: flex;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid #cfcfcf;
}
.playItem:last-child {
  border-bottom: none;
}
.playContent {
  margin-left: 20px;
  color: #999;
}

.matchImg {
  width: 80px;
  height: 80px;
  margin-right: 10px;
}
.playImage {
  width: 80px;
  height: 80px;
}

.playWrap {
  display: flex;
}
.livePicture {
  width: 40%;
  height: 400px;
}
</style>

3:index.html记得加入如下代码

 <link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.11.4/video-js.css" rel="stylesheet">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.11.4/video.min.js"></script>
  <script src="https://player.live-video.net/1.4.0/amazon-ivs-videojs-tech.min.js"></script>

end
加油~~~~

到此这篇关于Vue实现直播功能的文章就介绍到这了,更多相关Vue实现直播内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue 莹石摄像头直播视频实例代码

    Vue 莹石摄像头直播视频代码. HTML代码: <div class="mainClass" v-show="rtmp_url!=''"> <video id="myPlayer" controls playsinline webkit-playsinline autoplay> <source type="application/x-mpegURL" :src="http_url&q

  • Vue-cli-webpack搭建斗鱼直播步骤详解

    前言 想必大家都看过斗鱼直播吧?这次在下使用从github上面摸下来的API,为大家重现一下斗鱼网站的搭建,使用vue-cli-webpack来实现. 声明 本文章所用API均从网络获取,本文作者不承担任何法律责任,请阅读本文的小伙伴们用于学习用途,不能用于商业! 如有侵权行为,请与作者联系,作者将于2日内删除. 效果 pc端 移动端 开始 好,扯了这么久的淡,该开始构建项目了 项目初始化 初始化文件夹 打开一个新文件夹,在命令行输入: vue init webpack 如果显示vue not

  • vue实现直播间点赞飘心效果的示例代码

    前言: 在开发公司项目的时候,遇到了直播间的一些功能,其中点赞冒泡飘心,就折腾了好久,canvas学的不好,自己写不来,百度找了一堆都是js原生写法,迁移到vue项目里来好多问题,百度也解决不了.自己试着慢慢解决,竟然在不知不觉中通了!废话不多说,直接上代码,复制粘贴即可使用 示例: 不动就不动吧.png ```第一步```:先在外部新建一个js文件,取名index.js(名字自己随便取) index.js代码内容如下: /** * LikeHeart * @version: 1.0.0 * @

  • 基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

    一.项目简介 uni-liveShow是一个基于vue+uni-app技术开发的集小视频/IM聊天/直播等功能于一体的微直播项目.界面仿制抖音|火山小视频/陌陌直播,支持编译到多端(H5.小程序.App端) 且兼容效果一致. 二.效果预览 在H5.小程序.App端测试效果如下:(后续大图均为APP端) 三.使用技术 编码器+技术:HBuilderX + vue/NVue/uniapp/vuex iconfont图标:阿里字体图标库 自定义导航栏 + 底部Tabbar 弹窗组件:uniPop(un

  • 2分钟实现一个Vue实时直播系统的示例代码

    前言 我们在不敲代码的时候可能会去看游戏直播,那么是前台怎么实现的呢?下面我们来讲一下. 第一步,购买云直播服务 首先,你必须去阿里云或者腾讯云注册一个直播服务.也花不了几个钱,练手的话,几十块钱就够了. 这里我拿阿里云举例,购买完了,配置好推流域名跟播流域名,下面我们将进行地址生成.记住下面生成的地址,下面会用到. 第二步,下载本地推流工具 https://obsproject.com/ 第三步,设置OBS 在第一步中图片底部有推流地址,需要注意,分为两部分填入下方图所示. 在AppName字

  • vue+webrtc(腾讯云) 实现直播功能的实践

    目录 1.直播效果 2.开直播步骤 2.1引入腾讯web端(快直播)脚本 2.2在需要使用直播的界面 添加一个视频容器(开启直播后,显示视频的位置) 2.3创建直播对象,开启直播 2.4关闭直播 1.直播效果 1.pc端 2.移动端 2.开直播步骤 2.1引入腾讯web端(快直播)脚本 脚本必须引入在 index.heml的body中 <body style="padding:0;margin:0"> //腾讯快直播脚本 <script src="https

  • 详解Vue实现直播功能

    最近公司刚好在做直播,那么今天就记录一下遇到的坑,公司服务器用的亚马逊aws,所以直接看官方的api就可以了,aws官方地址aws直播api 先看下具体的实现后的效果图把 按照网上成熟的方法,使用的是video.js,然后aws做了一层封装,那么我们直接拿来使用把,这里使用vue版本的vue-video-player 先安装下相关的包 npm install vue-video-player --save 在main.js引入vue-video-player // 第一个是videoJs的样式,

  • 详解vue更改头像功能实现

    如上图所示:需要完成的功能是点击更改头像,获取本地文件库,选择图片后将原始图片替换.这里我就直接用html文件引入vue来简单实现在这功能,代码如下: HTML: <div id="app"> <div class="item_bock head_p"> <div class="head_img"> <img :src="userInfo.avatar"/> <--图片地址

  • 详解vue实现坐标拾取器功能示例

    需求 1.搜索具体地址,自动填写经纬度,并在地图上标记 2.点击地图上一点,可重新填写经纬度并且标记 代码 在dom新建div渲染地图 <el-form-item label="店铺地址" prop="address"> <el-input v-model="fristForm.address"></el-input> <el-input class="long-lat" v-mode

  • antd Vue实现Login登录页面布局案例详解 附带验证码验证功能

    效果 Login页面 <!-- * @Author: Jackie * @Date: 2022-05-07 14:34:06 * @LastEditTime: 2022-05-09 15:57:44 * @LastEditors: Jackie * @Description: 登录页 用户名-密码-验证码登录方式 * @FilePath: /vue-admin-template/src/views/Login.vue * @version: --> <template> <d

  • 详解 vue.js用法和特性

    前  言 最近用Vue.js做了一个数据查询平台,还做了一个拼图游戏,突然深深的感到了vue的强大. Vue.js是一套构建用户界面(user interface)的渐进式框架.与其他重量级框架不同的是,Vue 从根本上采用最小成本.渐进增量(incrementally adoptable)的设计.Vue 的核心库只专注于视图层,并且很容易与其他第三方库或现有项目集成.另一方面,当与单文件组件和 Vue 生态系统支持的库结合使用时,Vue 也完全能够为复杂的单页应用程序提供有力驱动. Vue.j

  • 详解vue组件基础

    什么是组件 组件(Component)是对数据和方法的简单封装.web中的组件其实可以看成是页面的一个组成部分,它是一个具有独立的逻辑和功能的界面,同时又能根据规定的接口规则进行相互融和,最终成为一个完整的应用,页面就是由一个个类似这样的组成部分组成的,比如导航.列表.弹窗.下拉菜单等.页面只不过是这样组件的容器,组件自由组合形成功能完整的界面,当不需要某个组件,或者想要替换某个组件时,可以随时进行替换和删除,而不影响整个应用的运行..前端组件化的核心思想就是将一个巨大复杂的东西拆分成粒度合理的

  • 详解vue高级特性

    Vue为我们提供了很多高级特性,学习和掌握它们有助于提高你的代码水平. 一.watch进阶 从我们刚开始学习Vue的时候,对于侦听属性,都是简单地如下面一般使用: watch:{ a(){ //doSomething } } 实际上,Vue对watch提供了很多进阶用法. handler函数 以对象和handler函数的方式来定义一个监听属性,handler就是处理监听变动时的函数: watch:{ a:{ handler:'doSomething' } }, methods:{ doSomet

  • 详解Vue之事件处理

    在Vue进行前端开发中,事件监听是必不可少的功能,本文通过简单的小例子,简述v-on的简单用法,仅供学习分享使用,如有不足之处,还请指正. 监听事件 可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码.如下所示: <button v-on:click="counter += 1">Add 1</button> <p>按钮被点击了 {{ counter }} 次.</p> 其中counter为Vue自定

  • 详解Vue.js 响应接口

    Vue 可以添加数据动态响应接口. 例如以下实例,我们通过使用 $watch 属性来实现数据的监听,$watch 必须添加在 Vue 实例之外才能实现正确的响应. 实例中通过点击按钮计数器会加 1.setTimeout 设置 10 秒后计算器的值加上 20 . <div id = "app"> <p style = "font-size:25px;">计数器: {{ counter }}</p> <button @click

  • 详解vue-flickity的fullScreen功能实现

    描述 在项目集成了vue-flickity组件后发现,该组件参考flickity官网的fullscreen配置不起作用 实现方法 需要添加flickity-fullscreen组件 在main.js中导入flickity-fullscreen组件 添加flickity组件的fullscreen属性 定义fullscreen的CSS样式 具体步骤 1.添加flickity-fullscreen组件 需要提前配置好flickity yarn: yarn add flickity-fullscreen

随机推荐