nginx实现代理转发 阿里云视频点播
1. 开通阿里云视频点播 官方介绍
视频点播(ApsaraVideo VoD,简称VoD)是集视频采集、编辑、上传、媒体资源管理、自动化转码处理(窄带高清TM)、视频审核分析、分发加速于一体的一站式音视频点播解决方案。
2. 音视频加速服务 配置后,即可使用音视频分发加速(就近访问,缓存)服务,提升播放体验,产生的加速流量可通过购买流量包抵扣,更优惠;如您未配置域名,播放将产生存储流出流量,具体请参见产品定价
添加播放域名
用于内容分发加速,提供更好播放体验
配置CNAME
将视频点播分配的CNAME指向域名
https://help.aliyun.com/document_detail/86076.html?spm=5176.12672711.0.0.79601fa3O1ssk1
配置域名
按需配置访问控制、缓存过期时间、回源设置及HTTPS安全加速等
3. 服务端开发API 使用HttpClient请求api里面提供的固定的路径,路径里面拼接固定的参数
事例
1 2 3 4 5 6 7 http://vod.cn-shanghai.aliyuncs.com/ ?Action=CreateUploadVideo &Title=exampleTitle &FileName=example.avi &FileSize=10485760 &Format=JSON &<公共参数>
4. 服务端SDK-封装API 点播服务(VoD)基于对象存储(OSS)构建,开通VoD时会自动分配独立的系统Bucket,以存储各种媒体文件,包括上传的视频、音频、图片等源文件,以及转码后的输出文件、截图和封面等等,并作为点播加速域名的源站。使用VoD上传SDK能方便、快速实现媒体文件的上传
https://help.aliyun.com/document_detail/53406.html?spm=a2c4g.11186623.6.1063.6acd7bdc1IZFyz
返回的json数据
1 信息 : {"PlayAuth":"...","VideoMeta":{"Status":"Normal","VideoId":"...","Title":"Flour.flv","CoverURL":"...","Duration":2.694000005722046},"RequestId":"..."}
4.1. Maven依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <dependency > <groupId > com.aliyun</groupId > <artifactId > aliyun-java-sdk-core</artifactId > <version > 4.3.3</version > </dependency > <dependency > <groupId > com.aliyun</groupId > <artifactId > aliyun-java-sdk-vod</artifactId > <version > 2.15.5</version > </dependency > <dependency > <groupId > com.google.code.gson</groupId > <artifactId > gson</artifactId > <version > 2.8.2</version > </dependency >
4.2. 初始化 1 2 3 4 5 6 7 8 9 10 import com.aliyuncs.profile.DefaultProfile;import com.aliyuncs.DefaultAcsClient;import com.aliyuncs.exceptions.ClientException;public static DefaultAcsClient initVodClient (String accessKeyId, String accessKeySecret) throws ClientException { String regionId = "cn-shanghai" ; DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret); DefaultAcsClient client = new DefaultAcsClient (profile); return client; }
4.3. 得到数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public static void main (String[] argv) throws ClientException { DefaultAcsClient client = AliyunVodSDKUtils.initVodClient("<Your AccessKeyId>" , "<Your AccessKeySecret>" ); GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest (); try { request.setVideoId("<video id>" ); GetVideoPlayAuthResponse response = client.getAcsResponse(request); System.out.print("PlayAuth = " + response.getPlayAuth() + "\n" ); System.out.print("CoverURL = " + response.getVideoMeta().getCoverURL() + "\n" ); System.out.print("CoverTitle = " + response.getVideoMeta().getTitle() + "\n" ); } catch (Exception e) { System.out.print("ErrorMessage = " + e.getLocalizedMessage()); } }
5. 视频安全 https://help.aliyun.com/document_detail/99436.html?spm=a2c4g.11186623.6.669.2a402970yUpZ9Y
6. java上传SDK https://help.aliyun.com/document_detail/53406.html?spm=a2c4g.11186623.6.1063.76e4419aYnHbp9
6.1. 安装 按照步骤测试上传 – aliyun-java-vod-upload-1.4.9.jar需要自己上传
以 1.4.9 版本为例,步骤如下:
1.下载Java示例代码VODUploadDemo-java-1.4.9.zip开发包(包含示例代码和所需jar包), 见 视频上传SDK下载 ;
2.将解压后lib目录下的所有jar文件拷贝至您的项目中;
3.SDK依赖的jar包版本说明
注意:以下列举出部分依赖jar包的版本,您可直接在您的项目中添加maven依赖,也可以将VODUploadDemo-java-1.4.9.zip包中的所有jar包引入您的项目中使用。其中,aliyun-java-vod-upload-1.4.9.jar 还未正式开源,请您直接引入jar包至您的项目中使用。
6.2. 下载Maven依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <dependency > <groupId > com.aliyun</groupId > <artifactId > aliyun-java-sdk-core</artifactId > <version > 4.3.3</version > </dependency > <dependency > <groupId > com.aliyun.oss</groupId > <artifactId > aliyun-sdk-oss</artifactId > <version > 3.1.0</version > </dependency > <dependency > <groupId > com.aliyun</groupId > <artifactId > aliyun-java-sdk-vod</artifactId > <version > 2.15.2</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > fastjson</artifactId > <version > 1.2.28</version > </dependency > <dependency > <groupId > com.google.code.gson</groupId > <artifactId > gson</artifactId > <version > 2.8.2</version > </dependency > <dependency > <groupId > com.aliyun</groupId > <artifactId > aliyun-sdk-vod-upload</artifactId > <version > 1.4.11</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.10</version > <scope > test</scope > </dependency >
6.3. 手动导入aliyun-java-vod-upload jar包到maven仓库 进入到下载的文件夹下
1 $ mvn install:install-file -DgroupId=com.aliyun -DartifactId=aliyun-sdk-vod-upload -Dversion=1.4.11 -Dpackaging=jar -Dfile=aliyun-java-vod-upload-1.4.11.jar
6.4. 测试本地上传 - 得到VideoId 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 private static void testUploadVideo () { String title = "Squirrel" ; String fileName = "视频本地完整路径" ; UploadVideoRequest request = new UploadVideoRequest (accessKeyId, accessKeySecret, title, fileName); request.setPartSize(2 * 1024 * 1024L ); request.setTaskNum(1 ); UploadVideoImpl uploader = new UploadVideoImpl (); UploadVideoResponse response = uploader.uploadVideo(request); System.out.print("RequestId=" + response.getRequestId() + "\n" ); if (response.isSuccess()) { System.out.print("VideoId=" + response.getVideoId() + "\n" ); } else { System.out.print("VideoId=" + response.getVideoId() + "\n" ); System.out.print("ErrorCode=" + response.getCode() + "\n" ); System.out.print("ErrorMessage=" + response.getMessage() + "\n" ); } }
6.5. 获取播放凭证 - PlayAuth 仅需要输入videoId
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import com.aliyuncs.DefaultAcsClient;import com.aliyuncs.exceptions.ClientException;import com.aliyuncs.profile.DefaultProfile;public class AliyunVodSDKUtils { public static DefaultAcsClient initVodClient (String accessKeyId, String accessKeySecret) throws ClientException { String regionId = "cn-shanghai" ; DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret); DefaultAcsClient client = new DefaultAcsClient (profile); return client; } } public static void getInfo () throws ClientException { DefaultAcsClient client = AliyunVodSDKUtils.initVodClient(accessKeyId, accessKeySecret); GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest (); try { request.setVideoId("<video id>" ); GetVideoPlayAuthResponse response = client.getAcsResponse(request); System.out.print("PlayAuth = " + response.getPlayAuth() + "\n" ); System.out.print("CoverURL = " + response.getVideoMeta().getCoverURL() + "\n" ); System.out.print("VideoTitle = " + response.getVideoMeta().getTitle() + "\n" ); } catch (Exception e) { System.out.print("ErrorMessage = " + e.getLocalizedMessage()); } }
6.6. 播放视频 视频点播控制器中点击视频管理,可以看到web播放器代码,复制里面的html代码
6.7. 直接通过地址播放 id 对应组件中的id
autoplay 是否自动播放
width, height 视频宽,高
source 视频地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <!DOCTYPE HTML > <html > <head > <meta charset ="UTF-8" > <meta http-equiv ="x-ua-compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, height=device-height, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <title > Vod</title > <link rel ="stylesheet" href ="https://g.alicdn.com/de/prismplayer/2.6.0/skins/default/aliplayer-min.css" /> <script type ="text/javascript" src ="https://g.alicdn.com/de/prismplayer/2.6.0/aliplayer-min.js" > </script > </head > <body > <div class ="prism-player" id ="J_prismPlayer" > </div > <script > var player = new Aliplayer ({ id : "J_prismPlayer" , autoplay : true , width :"1920px" , height :"1280px" , source : "<视频播放地址>" , cover : '' }); </script > </body >
6.8. 获取播放凭证 PlayAuth后播放 vid, playauth, cover 都可以通过getInfo方法得到
注意:播放凭证有过期时间,默认值:100秒 。取值范围:100~3000 。
request.setAuthInfoTimeout(200L);
配置凭证有效时间
在线配置参考:https://player.alicdn.com/aliplayer/setting/setting.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <!DOCTYPE HTML > <html > <head > <meta charset ="UTF-8" > <meta http-equiv ="x-ua-compatible" content ="IE=edge" > <meta name ="viewport" content ="width=device-width, height=device-height, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <title > Vod</title > <link rel ="stylesheet" href ="https://g.alicdn.com/de/prismplayer/2.6.0/skins/default/aliplayer-min.css" /> <script type ="text/javascript" src ="https://g.alicdn.com/de/prismplayer/2.6.0/aliplayer-min.js" > </script > </head > <body > <div class ="prism-player" id ="J_prismPlayer" > </div > <script > var player = new Aliplayer ({ id : "J_prismPlayer" , autoplay : true , width :"1920px" , height :"1280px" , vid :"<video id>" , playauth :'< >' , cover :'<>' }); </script > </body >
7. 视频上传后端 新建videoservice项目
7.1. application.yml 1 2 3 4 5 6 7 8 9 10 server: port: 8002 spring: application: name: online-video profiles: active: dev
7.2. 端口仍为8080–配置文件没有生效 点击项目的Open Module Settings
根据文件选择相应文件标记
7.3. Maven依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 <dependencies > <dependency > <groupId > com.online.edu</groupId > <artifactId > educommon</artifactId > <version > 0.0.1-SNAPSHOT</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.10</version > <scope > test</scope > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-configuration-processor</artifactId > <optional > true</optional > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <optional > true</optional > </dependency > <dependency > <groupId > io.springfox</groupId > <artifactId > springfox-swagger2</artifactId > </dependency > <dependency > <groupId > io.springfox</groupId > <artifactId > springfox-swagger-ui</artifactId > </dependency > <dependency > <groupId > com.aliyun</groupId > <artifactId > aliyun-java-sdk-core</artifactId > <version > 4.3.3</version > </dependency > <dependency > <groupId > com.aliyun.oss</groupId > <artifactId > aliyun-sdk-oss</artifactId > <version > 3.1.0</version > </dependency > <dependency > <groupId > com.aliyun</groupId > <artifactId > aliyun-java-sdk-vod</artifactId > <version > 2.15.2</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > fastjson</artifactId > <version > 1.2.28</version > </dependency > <dependency > <groupId > com.google.code.gson</groupId > <artifactId > gson</artifactId > <version > 2.8.2</version > </dependency > <dependency > <groupId > com.aliyun</groupId > <artifactId > aliyun-sdk-vod-upload</artifactId > <version > 1.4.11</version > </dependency > </dependencies >
7.4. 配置阿里云accessKeyId,accessKeySecret 1 2 3 4 5 aliyun: oss: file: accessKeyId: <Your accessKeyId> accessKeySecret: <Your accessKeySecret>
7.5. VideoService 1 2 3 4 5 6 7 package com.online.edu.videoservice.service;import org.springframework.web.multipart.MultipartFile;public interface VideoService { String uploadVideo (MultipartFile file) ; }
7.6. AliyunVodSDKUtils 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.online.edu.videoservice.utils;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Configuration;@Data @Configuration @ConfigurationProperties(prefix = "aliyun.oss.file") public class AliyunVodSDKUtils { private String accessKeyId; private String accessKeySecret; }
7.7. VideoServiceImpl-文件流上传 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 package com.online.edu.videoservice.service.impl;import com.aliyun.vod.upload.impl.UploadVideoImpl;import com.aliyun.vod.upload.req.UploadFileStreamRequest;import com.aliyun.vod.upload.req.UploadStreamRequest;import com.aliyun.vod.upload.resp.UploadStreamResponse;import com.online.edu.videoservice.exception.VideoException;import com.online.edu.videoservice.service.VideoService;import com.online.edu.videoservice.utils.AliyunVodSDKUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.web.multipart.MultipartFile;import java.io.IOException;import java.io.InputStream;@Service public class VideoServiceImpl implements VideoService { @Autowired AliyunVodSDKUtils utils; @Override public String uploadVideo (MultipartFile file) { String fileName = file.getOriginalFilename(); String title = fileName.substring(0 ,fileName.lastIndexOf("." )); String videoId = null ; String errorMessage = null ; try { InputStream inputStream = file.getInputStream(); UploadStreamRequest request = new UploadStreamRequest ( utils.getAccessKeyId(),utils.getAccessKeySecret(),title,fileName,inputStream); UploadVideoImpl uploadVideo = new UploadVideoImpl (); UploadStreamResponse response = uploadVideo.uploadStream(request); if (response.isSuccess()) { videoId= response.getVideoId(); } else { videoId=response.getVideoId(); errorMessage=response.getMessage(); } } catch (IOException e) { throw new VideoException (20001 ,errorMessage); } return videoId; } }
7.8. VideoController - 返回videoId 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.online.edu.videoservice.controller;import com.online.edu.common.R;import com.online.edu.videoservice.service.VideoService;import io.swagger.annotations.ApiParam;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import org.springframework.web.multipart.MultipartFile;@RestController @CrossOrigin @RequestMapping("/videoservice/video") public class VideoController { @Autowired VideoService videoService; @PostMapping("/upload") public R uploadVideo (@ApiParam("视频文件") @RequestParam("file") MultipartFile file) { String videoId = videoService.uploadVideo(file); return R.ok().data("videoId" ,videoId); } }
8. 后端删除视频-ByVideoId 8.1. AliyunVodSDKUtils-initVodClient 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.online.edu.videoservice.utils;import com.aliyun.oss.ClientException;import com.aliyuncs.DefaultAcsClient;import com.aliyuncs.profile.DefaultProfile;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Configuration;@Data @Configuration @ConfigurationProperties(prefix = "aliyun.oss.file") public class AliyunVodSDKUtils { private String accessKeyId; private String accessKeySecret; public static DefaultAcsClient initVodClient (String accessKeyId, String accessKeySecret) throws ClientException { String regionId = "cn-shanghai" ; DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret); DefaultAcsClient client = new DefaultAcsClient (profile); return client; } }
8.2. VideoServiceImpl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Override public void deleteVideoById (String videoId) { String keyId = utils.getAccessKeyId(); String keySecret = utils.getAccessKeySecret(); try { DefaultAcsClient client = AliyunVodSDKUtils.initVodClient(keyId, keySecret); DeleteVideoRequest request = new DeleteVideoRequest (); request.setVideoIds(videoId); DeleteVideoResponse response = client.getAcsResponse(request); } catch (ClientException e) { throw new VideoException (20001 ,e.getLocalizedMessage()); } }
8.3. VideoController 1 2 3 4 5 @DeleteMapping("/delete/{videoId}") public R deleteById (@PathVariable String videoId) { videoService.deleteVideoById(videoId); return R.ok().message("删除视频成功" ); }
9. 配置nginx代理转发 路由中含 videoservice 转至8002端口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 server { listen 9500; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } location ~ /eduservice/ { proxy_pass http://localhost:8001; } location ~ /videoservice/ { proxy_pass http://localhost:8002; } }
10. 前端-整合在发布课程的章节页面 10.1. chapter.vue 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <el-form-item label="视频上传" :label-width="formLabelWidth"> <el-upload :before-remove="beforeRemove" :on-remove="handleRemove" :file-list="fileList" :on-success="uploadVideotoAliyun" :action="path" :name="file"> <el-button size="small" type="primary" :disabled="uploadDisable">点击上传</el-button> <el-tooltip placement="right-end" effect="light"> <div slot="content">最大支持1G,<br> 支持3GP、ASF、AVI、DAT、DV、FLV、F4V、<br> GIF、M2T、M4V、MJ2、MJPEG、MKV、MOV、MP4、<br> MPE、MPG、MPEG、MTS、OGG、QT、RM、RMVB、<br> SWF、TS、VOB、WMV、WEBM 等视频格式上传</div> <i class="el-icon-question"/> </el-tooltip> </el-upload> </el-form-item> <script> export default{ data(){ return{ path:'http://localhost:8002/videoservice/video/upload', fileList:[] } }, methods:{ //视频上传成功返回videoId uploadVideotoAliyun(response,file){ //console.log(response) this.uploadDisable = true this.videoObj.videoSourceId = response.data.videoId this.videoObj.size=file.size } } } </script>
10.2. 413错误(Request Entity Too Large )- 文件大小 nginx: client_max_body_size 1024m;
上传文件最大1M
1 org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.
调整文件上传限制
1 2 3 4 spring: servlet: multipart: max-file-size: 1024MB
11. 前端- 删除视频 :before-remove="beforeRemove"
删除前,提示是否删除:on-remove="handleRemove"
删除时,真正删除数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <script> //上传成功后删除该文件时 beforeRemove(file,fileList){ return this.$confirm(`确定删除${file.name},重新上传? `); }, //删除时的方法调用 handleRemove(file,fileList){ console.log(file) video.deleteAliyunById(this.videoObj.videoSourceId) .then(response => { this.$message({ type: 'success', message: response.message }) this.uploadDisable=false }).catch() } </script>
12. 数据回显 当修改时,上传视频的按钮下应该有当时提交的文件显示
12.1. edu_video 添加字段 video_original_name 1 alter table edu_video add column video_original_name varchar (50 ) default null comment '视频名称'
12.2. EduVideo 添加成员变量videoOriginalName 1 2 @ApiModelProperty(value = "视频名称") private String videoOriginalName;
12.3. 取得数据 视频上传成功时返回的文件数据
1 2 3 4 5 status: "success" name: "Flour.flv" size: 426359 percentage: 100 uid: 1583657471662
获取视频名
1 2 3 4 5 6 7 8 9 10 <script> //视频上传成功返回videoId uploadVideotoAliyun(response,file,fileList){ //console.log(response) this.uploadDisable = true this.videoObj.videoSourceId = response.data.videoId this.videoObj.videoOriginalName = file.name this.videoObj.size=file.size } </script>
12.4. 在编辑课程时,回显 1 2 3 4 5 6 7 8 9 <script> getVideoById(id){ video.selectVideoById(id).then(response=>{ this.videoObj=response.data.items //上传成功文件列表 this.fileList = [{'name':this.videoObj.videoOriginalName}] }) } </script>
12.5. 整体效果