zoukankan      html  css  js  c++  java
  • luffy_06

    06视频播放

    项目中有两种视频:收费视频[需要加密]和免费视频

    使用保利威云视频服务来对视频进行加密

    官方网址: http://www.polyv.net/vod/

    注意:

    开发时通过免费试用注册体验版账号

    公司使用酷播尊享版

    1557993340983

    开发文档地址:http://dev.polyv.net/2017/videoproduct/v-playerapi/html5player/html5-docs/

    要开发播放保利威的加密视频功能,需要在用户中心->设置->API接口和加密设置.

    http://my.polyv.net/secure/setting/api

    1557993716875

    配置视频上传加密.

    1557993844826

    上传视频并记录视频的VID

    1557994524173

    后端获取保利威的视频播放授权token,提供接口api给前端

    参考文档:http://dev.polyv.net/2019/videoproduct/v-api/v-api-play/create-playsafe-token/

    根据官方文档的案例,已经有其他人开源了,针对polvy的token生成的python版本了,我们可以直接拿来使用.

    在libs下创建polyv.py,编写token生成工具函数

    from django.conf import settings
    import time
    import requests
    import hashlib
    
    class PolyvPlayer(object):
        userId = settings.POLYV_CONFIG['userId']
        secretkey = settings.POLYV_CONFIG['secretkey']
    
        def tomd5(self, value):
            """取md5值"""
            return hashlib.md5(value.encode()).hexdigest()
    
        # 获取视频数据的token
        def get_video_token(self, videoId, viewerIp, viewerId=None, viewerName='', extraParams='HTML5'):
            """
            :param videoId: 视频id
            :param viewerId: 看视频用户id
            :param viewerIp: 看视频用户ip
            :param viewerName: 看视频用户昵称
            :param extraParams: 扩展参数
            :param sign: 加密的sign
            :return: 返回点播的视频的token
            """
            ts = int(time.time() * 1000)  # 时间戳
            plain = {
                "userId": self.userId,
                'videoId': videoId,
                'ts': ts,
                'viewerId': viewerId,
                'viewerIp': viewerIp,
                'viewerName': viewerName,
                'extraParams': extraParams
            }
    
            # 按照ASCKII升序 key + value + key + value... + value 拼接
            plain_sorted = {}
            key_temp = sorted(plain)
            for key in key_temp:
                plain_sorted[key] = plain[key]
            print(plain_sorted)
    
            plain_string = ''
            for k, v in plain_sorted.items():
                plain_string += str(k) + str(v)
            print(plain_string)
    
            sign_data = self.secretkey + plain_string + self.secretkey
    
            # 取sign_data的md5的大写
            sign = self.tomd5(sign_data).upper()
    
            # 新的带有sign的字典
            plain.update({'sign': sign})
    
            result = requests.post(
                url='https://hls.videocc.net/service/v1/token',
                headers={"Content-type": "application/x-www-form-urlencoded"},
                data=plain
            ).json()
            data = {} if isinstance(result, str) else result.get("data", {})
    
            return {"token": data}
    

    配置文件settings/dev.py,代码:

    # 保利威视频加密服务
    POLYV_CONFIG = {
        "userId":"62dc475e3f",
        "secretkey":"h6FiaEBRMU",
        "servicesUrl":"https://hls.videocc.net/service/v1/token",
    }
    

    视图代码:

    from rest_framework.views import APIView
    from luffy.libs.polyv import PolyvPlayer
    from rest_framework.response import Response
    from rest_framework.permissions import IsAuthenticated
    
    
    class PolyvAPIView(APIView):
        """视屏加密服务"""
        """生成播放视频的playsafetoken"""
        """播放页面的当前访问者只能是用户,不能是游客"""
        def get(self, request):
            # 获取客户端要播放的视屏的vid
            vid = request.query_parms.get('vid')
            
            # 获取客户端的IP
            remote_addr = request.META.get('REMOTE_ADDR')
            
            # 获取用户的ID和用户名--test
            user_id = 1
            user_name = 'test'
            
            # 生成token
            polyv_video = PolyvPlayer()
            verify_data = polyv_video.get_video_token(vid, remote_addr, user_id, user_name)
            
            return Response(verify_data["token"])
    

    路由代码:

    path(r"polyv/token/",views.PolyvAPIView.as_view()),
    

    客户端请求token并播放视频

    在 vue项目的入口文件index.html 中加载保利威视频播放器的js核心类库

    <script src='https://player.polyv.net/script/polyvplayer.min.js'></script>
    

    创建视频播放页面的组件Player.vue,组件中直接配置保利威播放器需要的参数。

    Player.vue,代码:

    <template>
        <div class="player">
          <div id="player"></div>
        </div>
    </template>
    
    <script>
    export default {
      name:"Player",
      data () {
        return {
    
        }
      },
      methods: {
    
      },
      mounted(){
        let _this = this;
        var player = polyvObject('#player').videoPlayer({
            wrap: '#player',
             document.documentElement.clientWidth, // 宽度
            height: document.documentElement.clientHeight, // 高度
            forceH5: true,
            vid: '62dc475e3f09b6db69447011eed4415a_6',
            code: '骑士3期', // 一般是用户昵称
            // 视频加密播放的配置
            playsafe: function (vid, next) { // 向后端发送请求获取加密的token
                _this.$axios.get(_this.$settings.Host+`/courses/polyv/token/`,{
                  params:{
                    vid: "62dc475e3f09b6db69447011eed4415a_6",
                  }
                }).then(function (response) {
                    console.log(response);
                    next(response.data.token);
                })
    
            }
        });
      },
      computed: {
      }
    }
    </script>
    
    <style scoped>
    </style>
    

    前端路由,代码:

          {
           name:"Player",
           path:"/player",
           component: Player,
         },
    

    完善点击课程详情页的立即试学按钮跳转到视频播放页面,并发送vid

    Detail.vue,代码:

    课时章节:

    <button class="try" v-if="lesson.free_trail"><router-link :to="{path: '/player',query:{'vid':lesson.section_link}}">立即试学</router-link></button>
    

    **courses/serializers.py ** add 'section_link'

    class CourseLessonModelSerializer(serializers.ModelSerializer):
        """课程课时"""
        class Meta:
            model = CourseLesson
            fields = ['id', 'name', 'duration', 'free_trail', 'section_link']
    
    

    Player.vue,代码:

    获取vid视频ID

    <template>
        <div class="player">
          <div id="player"></div>
        </div>
    </template>
    
    <script>
    export default {
      name:"Player",
      data () {
        return {
    
        }
      },
      methods: {
    
      },
      mounted(){
        let _this = this;
        let video_id = this.$route.query.vid;
        var player = polyvObject('#player').videoPlayer({
            wrap: '#player',
             document.documentElement.clientWidth, // 宽度
            height: document.documentElement.clientHeight, // 高度
            forceH5: true,
            vid:video_id, // vid:vid,的简写
            code: '骑士3期', // 一般是用户昵称
            // 视频加密播放的配置
            playsafe: function (vid, next) { // 向后端发送请求获取加密的token
                _this.$axios.get(_this.$settings.Host+`/courses/polyv/token/`,{
                  params:{
                    vid:video_id,
                  }
                }).then(function (response) {
                    console.log(response);
                    next(response.data.token);
                })
    
            }
        });
      },
      computed: {
      }
    }
    </script>
    
    <style scoped>
    </style>
    
    

    完善API接口的身份认证

    试学必须在用户登录以后才能进行,所以后端的tokenAPI接口必须保证用户登陆以后,

    所以后端视图代码中增加对jwt token的识别认证,代码:

    from rest_framework.views import APIView
    from luffy.libs.polyv import PolyvPlayer
    from rest_framework.response import Response
    from rest_framework.permissions import IsAuthenticated
    class PolyvAPIView(APIView):
        """生成播放视频的playsafetoken"""
        """播放页面的当前访问者只能是用户,不能是游客"""
        permission_classes = (IsAuthenticated,)
        def get(self,request):
            # 获取客户端要播放的视频vid
            vid = request.query_params.get("vid")
            # 获取客户端的IP地址
            remote_addr = request.META.get("REMOTE_ADDR")
            # 获取用户的ID和用户名[测试]
            user_id = request.user.id
            user_name = request.user.username
    
            # 生成token
            polyv = PolyvPlayer()
            data = polyv.get_video_token(vid, remote_addr,user_id, user_name)
    
            return Response(data["token"])
    
    

    前端在请求后端提供视频加密播放的token时需要附带 jwt token

    Player.vue,代码:

    <template>
        <div class="player">
          <div id="player"></div>
        </div>
    </template>
    
    <script>
    export default {
      name:"Player",
      data () {
        return {
          token: sessionStorage.token || localStorage.token,
          user_id: sessionStorage.user_id || localStorage.user_id,
          user_name: sessionStorage.user_name || localStorage.user_name,
        }
      },
      methods: {
    
      },
      created(){
        // 判断用户用户是否已经登录了
        if(!this.token){
          let _this = this;
          this.$alert("对不起,您尚未登录!请登录!","警告",{
            callback(){
              _this.$router.push("/login");
            }
          })
        }
      },
      mounted(){
        let _this = this;
        let video_id = this.$route.query.vid;
        var player = polyvObject('#player').videoPlayer({
            wrap: '#player',
             document.documentElement.clientWidth, // 宽度
            height: document.documentElement.clientHeight, // 高度
            forceH5: true,
            vid:video_id, // vid:vid,的简写
            code: _this.user_name, // 跑马灯的显示信息,一般是用户昵称
            // 视频加密播放的配置
            playsafe: function (vid, next) { // 向后端发送请求获取加密的token
                _this.$axios.get(_this.$settings.Host+`/courses/polyv/token/`,{
                  // 附带jwt token
                  headers:{
                    // 注意下方的空格!!!
                    "Authorization":"jwt " + _this.token
                  },
                  params:{
                    vid:video_id,
                  }
                }).then(function (response) {
                    console.log(response);
                    next(response.data.token);
                })
    
            }
        });
      },
      computed: {
      }
    }
    </script>
    
    <style scoped>
    </style>
    
    

    详情页的视频免费播放

    在课程模型Courses/models.py中新增一个视频的字段

    from ckeditor_uploader.fields import RichTextUploadingField
    class Course(BaseModel):
        """
        专题课程
        """
     	
        video = models.FileField(upload_to="video", null=True,blank=True,default=None, verbose_name="封面视频")
    
    
    

    执行数据迁移

    python manage.py makemigrations
    python manage.py migrate
    
    

    前端修改播放器中关于视频地址和视频封面的地址

       watch:{
          course(data){
            // while(data.brief.search(`"/media`) != -1 ){
            //   data.brief = data.brief.replace(`"/media`,`"${this.$settings.Host}/media`)
            //
             // 替换视频地址
            this.playerOptions.sources[0].src = data.video;
            // 替换视频封面
            this.playerOptions.poster = data.course_img;
            // 替换科恒信息中的详情介绍里面的图片路径
            while(data.brief.search(`"/media`) != -1 ){
              data.brief = data.brief.replace(`"/media`,`"${this.$settings.Host}/media`)
            }
          }
    
    
  • 相关阅读:
    在Web服务调试时,出现IIS配置错误的相应解决办法
    Eclipse解决Launch error: Failed to connect to remote VM [duplicate]
    在Eclipse中应该怎样去修改Android应用程序的包名(注意按步骤修改)
    用Fragment实现Tab页面切换效果初步总结
    与像素无关的dp单位与像素单位px之间的转换
    在Andorid开发项目中遇到的Bug记录(续)
    java邮件
    图片上传实例
    java多线程总结一:线程的两种创建方式及优劣比较
    java多线程总结二:后台线程(守护线程)
  • 原文地址:https://www.cnblogs.com/pankypan/p/11300273.html
Copyright © 2011-2022 走看看