七牛云上的基本概念:
公开空间:可通过文件对象的 URL 直接访问。如果要使用七牛云存储的镜像存储功能,请设置空间的属性为公有。
私有空间:文件对象的访问则必须获得拥有者的授权才能访问。
资源:资源是七牛云存储服务中的逻辑存储单元。
AccessKey: 用于标识用户,用户将 AccessKey 放入访问请求,以便七牛云存储识别访问者的身份。
SecretKey: 是用于加密签名字符串和服务器端验证签名字符串的密钥。
如果将视频放在公开空间里,那么用户可以直接根据url下载视频,是不安全的,如果是付费视频,则必须放在私有空间里,这篇文章也是私有资源的处理。
首先需要有七牛云账号、创建空间,具体操作可参考:七牛云对象存储快速入门
接下来就是写代码。
1、七牛Python SDK安装:
pip install qiniu
或
easy_install qiniu
2、初始化:
在使用SDK 前,您需要一对有效的 AccessKey 和 SecretKey 签名授权。
可以通过如下步骤获得:
- 开通七牛开发者帐号
- 登录七牛开发者平台,查看 Access Key 和 Secret Key。
获取Access Key 和 Secret Key 后,调用如下两行代码进行初始化对接:
from qiniu import Auth
q = Auth(access_key, secret_key)
3、api编写,代码是契合本人所做的项目的,您不能够直接使用、api是大致相同的:
1 from qiniu import Auth, PersistentFop, urlsafe_base64_encode, BucketManager, build_batch_delete
2 from django.conf import settings
3 from rest_framework.decorators import list_route, detail_route
4 from tokenauth.decorators import is_login, admin_login
5
6 from course.models import Chapter
7 from course.serializers import ChapterSerializer
8 from course.errors import INVALID_USER, INVALID_PARAMS, VIDEO_NOT_EXIST, OPERATION_NOT_ALLOWED, \
9 COURSE_ALREADY_ONLINE, COURSE_ALREADY_OFFLINE, CHAPTER_NOT_EXIST
10 from course.exception_handler import CustomError
11
12 access_key = '你自己账号的access_key'
13 secret_key = '你自己账号的secret_key'
14 domain = '七牛云对象存储内容管理生成的外链默认域名'
15 bucket_name = '要上传的空间名称'
16 # 视频转码会用到私有队列,在七牛云资源主页多媒体处理点击立即添加
17 pipeline = '私有队列名称'
18
19 class ChapterViewSet(ModelViewSet):
20 """
21 章节 ViewSet
22 """
23 queryset = Chapter.objects.all().order_by('created_time')
24 serializer_class = ChapterSerializer
25
26 @list_route(methods=['get'])
27 @admin_login
28 def get_uptoken(self, request):
29 """
30 获取上传token,有效期一个小时,前台拿到uptoken就可以上传视频文件
31 :param request:
32 :return:
33 """
34 q = Auth(access_key, secret_key)
35 token = q.upload_token(bucket_name)
36 return Response({'uptoken': token})
37
38 @list_route(methods=['post'])
39 @admin_login
40 def transcode(self, request):
41 """
42 七牛云视频转码切片m3u8,返回转码后的key。将视频流切割成可由HTTP下载的一个个小的音视频流,并生成一个M3U8播放列表,客户端只需要获取资源的M3U8播放列表即可播放音视频。
43 并且返回该视频的元信息url,前台可通过此url获取视频的时长等信息
44 :param request:
45 :param key:
46 :return:
47 """
48 key = request.data.get('key', None)
49 if key is None:
50 raise CustomError(INVALID_PARAMS)
51 q = Auth(access_key, secret_key)
52 fops = 'avthumb/m3u8'
53 hls_name = 'hls' + UUIDTools.uuid1_hex()
54
55 saveas_key = urlsafe_base64_encode(bucket_name + ':' + hls_name)
56 fops = fops + '|saveas/' + saveas_key
57 # 视频转码完成回调函数
58 notify_url = settings.QINIU_CALLBACK_URL + 'api/v1.0/course/chapters/complete_transcode/'
59 pfop = PersistentFop(q, bucket_name, pipeline, notify_url)
60 ops = []
61 ops.append(fops)
62 ret, info = pfop.execute(key, ops, 1)
63 if ret is None:
64 raise CustomError(VIDEO_NOT_EXIST)
65
66 # 获取视频元信息链接
67 base_url = 'http://%s/%s?avinfo' % (domain, key)
68 avinfo_url = q.private_download_url(base_url)
69
70 return Response({'success': True, 'hls_name': hls_name, 'avinfo_url': avinfo_url})
71
72 @list_route(methods=['post'])
73 def complete_transcode(self, request):
74 """
75 七牛云视频转码完成回调
76 """
77 origin_key = request.data.get('inputKey', None)
78 code = request.data.get('code', -1)
79 if code == 0:
80 TranscodeRecode.objects.create(created_by=0, updated_by=0, key=origin_key)
81 chapter = Chapter.objects.filter(origin_key=origin_key).values().first()
82 if chapter is not None:
83 Chapter.objects.filter(pk=chapter.get('id')).update(is_transcoded=True)
84
85 return Response({'success': True})
86
87 @list_route(methods=['get'])
88 def ts_private_url(self, request):
89 """
90 视频播放授权,将m3u8文件中的ts资源的url批量改写成私有url,以临时获取访问权限,有效期一个小时。
91 :param request:
92 :param key: m3u8文件的key
93 :return:
94 """
95 key = request.GET.get('key', None)
96 if not key:
97 raise CustomError(INVALID_PARAMS)
98 q = Auth(access_key, secret_key)
99 base_url = 'https://%s/%s?pm3u8/0/expires/315360000' % (domain, key)
100 private_url = q.private_download_url(base_url, expires=3600)
101 return Response({'private_url': private_url})
102
103 @list_route(methods=['post'])
104 @admin_login
105 def delete_videos(self, request):
106 """
107 删除七牛云上的视频文件
108 :param request:
109 :param keys: 逗号隔开的key
110 :return:
111 """
112 keys = request.data.get('keys', None)
113 if not keys:
114 raise CustomError(INVALID_PARAMS)
115 keys = keys.split(',')
116 q = Auth(access_key, secret_key)
117 bucket = BucketManager(q)
118 ops = build_batch_delete(bucket_name, keys)
119 ret, info = bucket.batch(ops)
120 qiniu_response = info.text_body.replace('"', '\'')
121
122 return Response({'success': True, 'qiniu_response': qiniu_response})
123
124 @list_route(methods=['post'])
125 @admin_login
126 def screenshot(self, request):
127 """
128 七牛云视频截图
129 :param request:
130 :param key:
131 :param offset:
132 :return:
133 """
134 key = request.data.get('key', None)
135 offset = int(request.data.get('offset', -1))
136 if key is None or offset < 0:
137 raise CustomError(INVALID_PARAMS)
138
139 q = Auth(access_key, secret_key)
140 fops = 'vframe/jpg/offset/%d/w/480/h/360' % offset
141 jpg_name = 'jpg' + UUIDTools.uuid1_hex()
142
143 saveas_key = urlsafe_base64_encode(bucket_name + ':' + jpg_name)
144 fops = fops + '|saveas/' + saveas_key
145
156 pfop = PersistentFop(q, bucket_name, pipeline)
147 ops = []
148 ops.append(fops)
149 ret, info = pfop.execute(key, ops, 1)
150 if ret is None:
151 raise CustomError(VIDEO_NOT_EXIST)
152 base_url = 'https://%s/%s' % (domain, jpg_name)
154 # 可以设置token过期时间
154 jpg_url = q.private_download_url(base_url, expires=315360000)
155 print(jpg_url)
156
157 return Response({'success': True, "jpg_url": jpg_url})
生成的api如下:

前端调用步骤:
- 调用get_uptoken,获取上传授权token,拿到token后使用js根据七牛云上传接口上传视频;
- 上传成功后调用transcode切片成m3u8,返回m3u8文件资源名称和视频时长等信息;
- 用户点击播放时,调用ts_private_url获取访问权限(参数是步骤2返回的m3u8资源名称);
- 若需要视频截图(如封面图),可以调用screenshot接口;若需要删除存储在七牛云上的视频,可以调用delete_videos接口。
浙公网安备 33010602011771号