• 视频的上传及购买播放


    一、上传视频

    1:使用百度云:

    1. 登录百度云:https://cloud.baidu.com/ 进入管理控制台;
    2. 开通 “视频点播VOD” 服务;
    3. 在后台管理系统 --> 右上角“安全认证” --> 获取 “AccessKey”;
    4. 在 “视频点播VOD” 界面 --> 全局设置 --> 发布设置 --> 安全设置 --> 获取 “UserKey”;

    2:自定义转码设置:

    1、视频需经过加密在进行发布,先创建一个编码模板(配置如下):

    1. 容器:选择 HLS(Http Live Streaming);
    2. 编码规格:high高;
    3. 分辨率 (视频码率):1920_1080 (2500) ,2180_720 (1024) ,800*600 (512)等;
    4. 加密策略:Token;

    2、进入 媒资管理 进行视频上传,选择 自定义转码模板组

     二:视频的播放

    1、后端代码

    1. 获取 ‘tokon’ 的值(参照官方文档:https://cloud.baidu.com/doc/VOD/BestPractise.html#token.E8.AE.A1.E7.AE.97.E8.A7.84.E5.88.99
       1 # 获取tokon;
       2 def course_token(request):
       3     # video:是视频文件的完整链接
       4     file = request.GET.get('video')
       5     # 过期时间;
       6     expiration_time = int(time.time()) + 2 * 60 * 60
       7 
       8     USER_ID = settings.BAIDU_CLOUD_USER_ID
       9     USER_KEY = settings.BAIDU_CLOUD_USER_KEY
      10 
      11     # file=http://hemvpc6ui1kef2g0dd2.exp.bcevod.com/mda-igjsr8g7z7zqwnav/mda-igjsr8g7z7zqwnav.m3u8
      12     # 先获取扩展名;再通过‘/’分割取最后一个值,并将扩展名替换为空字符串;得到‘ID’;
      13     extension = os.path.splitext(file)[1]
      14     media_id = file.split('/')[-1].replace(extension, '')
      15 
      16     # 将‘USER_KEY’进行编码;后面的‘hmac.new()’只能接受bytes类型;
      17     # unicode->bytes=unicode.encode('utf-8')bytes
      18     key = USER_KEY.encode('utf-8')
      19     message = '/{0}/{1}'.format(media_id, expiration_time).encode('utf-8')
      20 
      21     # signature:生成签名;
      22     # disgestmod:指定加密方式;
      23     signature = hmac.new(key, message, digestmod=hashlib.sha256).hexdigest()
      24     token = '{0}_{1}_{2}'.format(signature, USER_ID, expiration_time)
      25     return restful.result(data={'token': token})

      (url 映射地址:cms/course_token)

    2、前端代码

    1. 下载 videojs 文件:http://sdk.bce.baidu.com/media-sdk/Baidu-T5Player-SDK-Web-v3.4.0.zip
    2. 将 videojs 文件的 js 文件添加到项目文件目录中,以便 HTML模板 引用;
       1 <!-- HTML中需引用的文件 -->
       2     <script src="{% static 'videojs/video.min.js' %}"></script>
       3     <script src="{% static 'videojs/videojs-contrib-hls.min.js' %}"></script>
       4     <script src="{% static 'videojs/videojs-contrib-quality-levels.min.js' %}"></script>
       5 
       6     <!-- 加载播放器 -->
       7     <script type="text/javascript" src="https://cdn.bdstatic.com/jwplayer/latest/cyberplayer.js"></script>
       8 
       9     <!-- 初始化播放器的 js 文件 -->
      10     <script src="{% static 'js/cms/course_detail.min.js' %}"></script>
    3. 并创建一个用来加载视频的容器;
      1 <div class="video-group">
      2     <span id="video-info" hidden data-video-url="{{ course.video_url }}"
      3           data-cover-url="{{ course.cover_url }}"></span>
      4     <!-- 用来存储播放器 -->
      5     <div id="playercontainer"></div>
      6 </div>
    4. 通过 js 初始化播放器,并传递视频地址;
       1 function CourseDetail() {
       2 
       3 }
       4 
       5 // 视频播放;
       6 CourseDetail.prototype.initPlayer = function () {
       7     var videoInfoSpan = $('#video-info');
       8     var video_url = videoInfoSpan.attr('data-video-url');
       9     var cover_url = videoInfoSpan.attr('data-cover-url');
      10     var player = cyberplayer("playercontainer").setup({
      11          '100%',
      12         height: '100%',
      13         file: video_url,            // 视频链接;
      14         image: cover_url,           // 封面图链接;
      15         autostart: false,           // 是否自动播放;
      16         stretching: 'uniform',      // 扩大;
      17         repeat: false,              // 是否重复;
      18         volume: 100,                // 音量;
      19         controls: true,             // 底部控制栏;
      20         primary: "flash",           // 使用flash;
      21         tokenEncrypt: true,         // 采用token加密;
      22         ak: '86dc62e1dbd4455080ab1cfc5e587b17', // AccessKey;
      23     });
      24     
      25     // 视频播放前的事件;
      26     player.on('beforePlay', function (e) {
      27         if (!/m3u8/.test(e.file)) {
      28             return;
      29         }
      30         xfzajax.get({
      31             'url': '/course/course_token/',
      32             'data': {
      33                 'video': video_url
      34             },
      35             'success': function (result) {
      36                 if (result['code'] === 200) {
      37                     var token = result['data']['token'];
      38                     // 将‘tokon’设置入‘player’中,使播放器获取视频密码;
      39                     player.setToken(e.file, token);
      40                 } else {
      41                     alert('token错误!')
      42                 }
      43             },
      44             'fail': function (error) {
      45                 console.log(error)
      46             }
      47         })
      48     })
      49 };
      50 
      51 CourseDetail.prototype.run = function () {
      52     this.initPlayer();
      53 };
      54 
      55 $(function () {
      56     var course = new CourseDetail();
      57     course.run()
      58 });
      View Code

    三、购买视频及播放;

    1、使用 PaysApi 

    1. 文档的使用及说明:https://www.paysapi.com/docindex
    2. 发起付款接口的说明文档:https://www.paysapi.com/docpay

    2、代

    1. Models及HTML模板
       1 # 支付页面模板;
       2 class CourseOrder(models.Model):
       3     uid = ShortUUIDField(primary_key=True)
       4     course = models.ForeignKey("Course",on_delete=models.DO_NOTHING)
       5     buyer = models.ForeignKey("xfzauth.User",on_delete=models.DO_NOTHING)
       6     amount = models.FloatField(default=0)
       7     pub_time = models.DateTimeField(auto_now_add=True)
       8     # 支付渠道:1:代表支付宝支付;2:代表微信支付;
       9     istype = models.SmallIntegerField(default=1)
      10     # 支付状态:1:代表未支付;2:代表支付成功;
      11     status = models.SmallIntegerField(default=1)
      View Code
       1 <!-- 部分相关HTML模板 -->
       2 <form action="https://pay.bbbapi.com/" method="post" id="pay-form">
       3     <input type="hidden" name="uid" value="49dc532695baa99e16e01bc0">
       4     <input type="hidden" name="price" value="{{ course.price }}">
       5     <input type="hidden" name="notify_url" value="{{ notify_url }}">
       6     <input type="hidden" name="return_url" value="{{ return_url }}">
       7     <input type="hidden" name="orderid" value="{{ order.pk }}">
       8     <input type="hidden" name="orderuid" value="{{ request.user.pk }}">
       9     <input type="hidden" name="goodsname" value="{{ course.title }}">
      10     <input type="hidden" name="key" value="">
      11     <!-- 微信与支付宝支付 -->
      12     <div class="pay-way">
      13         <label for="istype-wx" class="label">
      14             <input id="istype-wx" type="radio" name="istype" value="2">
      15             <span class="wx-btn fk-btn">
      16             <img src="http://nos.netease.com/test-edu-image/1BD9F69D6760CE1508D2269864AA54F8.png" alt="">
      17         </span>
      18         </label>
      19         <label for="istype-zfb" class="label">
      20             <input id="istype-zfb" type="radio" name="istype" value="1" checked>
      21             <span class="zfb-btn fk-btn"></span>
      22         </label>
      23         <div style="clear: both;"></div>
      24     </div>
      25     <div class="submit-group">
      26         <input type="submit" value="去支付" id="submit-btn" class="submit-btn">
      27     </div>
      28 </form>
      View Code
    2. 获取“key”值
       1 from utils import restful
       2 from apps.xfzauth.decorators import xfz_login_required
       3 from hashlib import md5
       4 
       5 # 获取“key”;用户登录的情况下;
       6 @xfz_login_required
       7 def course_order_key(request):
       8     goodsname = request.POST.get("goodsname")       # 商品名称;
       9     istype = request.POST.get("istype")             # 支付渠道;
      10     notify_url = request.POST.get("notify_url")     # 通知回调网址;
      11     orderid = request.POST.get("orderid")           # 商户自定义订单号;
      12     orderuid = str(request.user.pk)                 # 商户自定义客户号;
      13     price = request.POST.get("price")               # 价格;
      14     return_url = request.POST.get("return_url")     # 跳转网址;
      15 
      16     # 在官网个人账户设置中的“API接口信息”中获取“token”与“uid”的值:
      17     token = 'e6110f92abcb11040ba153967847b7a6'
      18     uid = '49dc532695baa99e16e01bc0'
      19 
      20     # 秘钥“key”的拼接顺序:goodsname + istype + notify_url + orderid + orderuid + price + return_url + token + uid
      21     key = md5((goodsname + istype + notify_url + orderid + orderuid + price + return_url + token + uid).encode(
      22         "utf-8")).hexdigest()
      23     return restful.result(data={"key": key})
      View Code
    3. 购买课程
       1 # 购买课程;
       2 @xfz_login_required
       3 def course_order(request, course_id):
       4     course = Course.objects.get(pk=course_id)
       5     order = CourseOrder.objects.create(course=course, buyer=request.user, status=1, amount=course.price)
       6     context = {
       7         'course': course,
       8         'order': order,
       9         # 跳转链接:/course/notify_url/;
      10         'notify_url': request.build_absolute_uri(reverse('course:notify_view')),
      11         'return_url': request.build_absolute_uri(reverse('course:course_detail', kwargs={"course_id": course.pk}))
      12     }
      13     return render(request, 'course/course_order.html', context=context)
      14 
      15 # 使用订单ID更新支付状态;(关闭CSRF保护)
      16 @csrf_exempt
      17 def notify_view(request):
      18     orderid = request.POST.get('orderid')
      19     CourseOrder.objects.filter(pk=orderid).update(status=2)
      20     return restful.ok()
      View Code
    4. 前端“js”文件
       1 function CourseOrder() {
       2 
       3 }
       4 
       5 CourseOrder.prototype.run = function () {
       6     this.OrderEvent();
       7 };
       8 
       9 // 订购事件;(发起付款接口时需处理的数据)
      10 CourseOrder.prototype.OrderEvent = (function () {
      11     var submitBtn = $("#submit-btn");
      12     submitBtn.click(function (event) {
      13         event.preventDefault();
      14         var goodsname = $("input[name='goodsname']").val();
      15         var istype = $("input[name='istype']:checked").val();
      16         var notify_url = $("input[name='notify_url']").val();
      17         var orderid = $("input[name='orderid']").val();
      18         var price = $("input[name='price']").val();
      19         var return_url = $("input[name='return_url']").val();
      20         xfzajax.post({
      21             'url': '/course/course_order_key/',
      22             'data': {
      23                 'goodsname': goodsname,
      24                 'istype': istype,
      25                 'notify_url': notify_url,
      26                 'orderid': orderid,
      27                 'price': price,
      28                 'return_url': return_url
      29             },
      30             'success': function (result) {
      31                 if(result['code'] === 200){
      32                     var key = result['data']['key'];
      33                     var keyInput = $("input[name='key']");
      34                     keyInput.val(key);
      35                     $("#pay-form").submit();
      36                 }
      37             }
      38         });
      39     });
      40 });
      41 
      42 $(function () {
      43     var order = new CourseOrder();
      44     order.run();
      45 });
      View Code
  • 相关阅读:
    (转)在IOS应用中从竖屏模式强制转换为横屏模式
    IOS设备屏幕旋转相关技术收集
    超级工厂模式
    (转) objectiveC中的接口@interface与泛型(id)
    (原创)IOS播放视频
    IOS检测网络连接状态(转)
    (转) MPMoviePlayerController 电影播放器—IOS开发
    Oracle分析表和索引
    How To Partition Existing Table Using DBMS_Redefinition
    不可用索引
  • 原文地址:https://www.cnblogs.com/liqiongming/p/11016434.html
Copyright © 2020-2023  润新知