项目中有两种视频:收费视频[需要加密]和免费视频
官方网址: http://www.polyv.net/vod/
注意:
开发时通过
免费试用
注册体验版账号公司使用酷播尊享版
开发文档地址:http://dev.polyv.net/2017/videoproduct/v-playerapi/html5player/html5-docs/
要开发播放保利威的加密视频功能,需要在用户中心->设置->API接口和加密设置.
http://my.polyv.net/secure/setting/api
配置视频上传加密.
上传视频并记录视频的VID
参考文档: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()),
在 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',
width: 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',
width: 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>
试学必须在用户登录以后才能进行,所以后端的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',
width: 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`)
}
}
原文:https://www.cnblogs.com/pankypan/p/11300273.html