33.阿里云视频点播服务和小节视频上传
一、阿里云视频点播服务
参考文章:
1、开通视频点播
产品->企业应用->视频云->视频点播->使用流量计费(事先冲个几毛钱就好了)
2、整体流程
使用视频点播实现音视频上传、存储、处理和播放的整体流程如下:
- 用户获取上传授权。
- VoD下发 上传地址和凭证 及 VideoId。
- 用户上传视频保存视频ID(VideoId)。
- 用户服务端获取播放凭证。
- VoD下发带时效的播放凭证。
- 用户服务端将播放凭证下发给客户端完成视频播放。
3、视频点播服务的基本使用
完整的参考文档
①设置转码格式
选择全局设置 > 转码设置,单击添加转码模板组。
在视频转码模板组页面,根据业务需求选择封装格式和清晰度。
或直接将已有的模板设置为默认即可
如使用转码,则转成的视频为私密视频(后面需要用到),需要配置域名才能访问。
②分类管理
选择全局设置 > 分类管理
③上传视频文件
选择媒资库 > 音视频,单击上传音视频
④配置域名
音视频上传完成后,必须配一个已备案的域名,并完成CNAME绑定
得到CNAME
在购买域名的服务商处的管理控制台配置域名解析
⑤在控制台查看视频
此时视频可以在阿里云控制台播放
⑥获取web播放器代码
二、JAVA实现上传视频到阿里云点播服务(实际OSS)
因为上传视频可以进行加密,使用加密之后的地址不能进行视频播放,在数据库中不存储地址,而是存储视频id。
1、创建子模块
在service模块中创建子模块service_vod,并引入相关依赖
<dependencies> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> </dependency> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-vod</artifactId> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-sdk-vod-upload</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> </dependency> </dependencies>
注意:依赖版本在父模块中已经定义,aliyun-sdk-vod-upload需要手动下载引入。
2、初始化操作,创建DefaultAcsClient对象
public class InitObject { 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; } }
3、根据视频id获取视频播放地址
public static void getPlayUrl() throws Exception{ //1 根据视频id获取视频地址 //创建初始化对象 DefaultAcsClient client = InitObject.initVodClient("LTAI4GAeLQ4ByaQARKZMnXyj", "JSh6nc9XFq2LjRNOBBgyKMCPhEE0c7"); //创建获取视频地址request和response GetPlayInfoRequest request = new GetPlayInfoRequest(); GetPlayInfoResponse response = new GetPlayInfoResponse(); //向request对象里面设置视频id request.setVideoId("1a6f31cf1b1f4db787157c86c0613e47"); //调用初始化对象里面的方法,传递request,获取数据 response = client.getAcsResponse(request); List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList(); //播放地址 for (GetPlayInfoResponse.PlayInfo playInfo : playInfoList) { System.out.print("PlayInfo.PlayURL = " + playInfo.getPlayURL() + "\n"); } //Base信息 System.out.print("VideoBase.Title = " + response.getVideoBase().getTitle() + "\n"); }
4、根据视频id获取视频播放凭证
public static void setPlayAuth() throws Exception{ //根据视频id获取视频播放凭证 //创建初始化对象 DefaultAcsClient client = InitObject.initVodClient("LTAI4GAeLQ4ByaQARKZMnXyj", "JSh6nc9XFq2LjRNOBBgyKMCPhEE0c7"); //创建获取视频播放凭证的request和response GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest(); GetVideoPlayAuthResponse response = new GetVideoPlayAuthResponse(); //向request对象里面设置视频id request.setVideoId("1a6f31cf1b1f4db787157c86c0613e47"); //调用初始化对象里面的方法,传递request,得到视频凭证 response = client.getAcsResponse(request); System.out.println("playauth:"+response.getPlayAuth()); }
5、上传视频到阿里云视频点播并获取视频id
public class TestVod { public static void main(String[] args) throws Exception{ String accessKeyId = "LTAI4GAeLQ4ByaQARKZMnXyj"; String accessKeySecret = "JSh6nc9XFq2LjRNOBBgyKMCPhEE0c7"; String title = "5 - What If I Want to Move Faster";//上传之后文件名称 String fileName = "E://6 - What If I Want to Move Faster.mp4";//本地文件路径和名称 UploadVideoRequest request = new UploadVideoRequest(accessKeyId, accessKeySecret, title, fileName); /* 可指定分片上传时每个分片的大小,默认为2M字节 */ request.setPartSize(2 * 1024 * 1024L); /* 可指定分片上传时的并发线程数,默认为1,(注:该配置会占用服务器CPU资源,需根据服务器情况指定)*/ request.setTaskNum(1); UploadVideoImpl uploader = new UploadVideoImpl(); UploadVideoResponse response = uploader.uploadVideo(request); System.out.print("RequestId=" + response.getRequestId() + "\n"); //请求视频点播服务的请求ID if (response.isSuccess()) { System.out.print("VideoId=" + response.getVideoId() + "\n"); } else { /* 如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因 */ System.out.print("VideoId=" + response.getVideoId() + "\n"); System.out.print("ErrorCode=" + response.getCode() + "\n"); System.out.print("ErrorMessage=" + response.getMessage() + "\n"); } } }
三、添加小节-上传视频功能(后端)
1、引入依赖
2、创建application.properties
# 服务端口 server.port=8003 # 服务名 spring.application.name=service-vod # 环境设置:dev、test、prod spring.profiles.active=dev #阿里云 vod #不同的服务器,地址不同 aliyun.vod.file.keyid=LTAI4GAeLQ4ByaQARKZMnXyj aliyun.vod.file.keysecret=JSh6nc9XFq2LjRNOBBgyKMCPhEE0c7 # 最大上传单个文件大小:默认1M spring.servlet.multipart.max-file-size=1024MB # 最大置总上传的数据大小 :默认10M spring.servlet.multipart.max-request-size=1024MB
3、创建启动类
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//参数表示不加载数据库 @ComponentScan(basePackages={"com.atguigu"}) public class VodApplication { public static void main(String[] args) { SpringApplication.run(VodApplication.class, args); } }
4、创建controller和service
VodController类
@RestController @RequestMapping("/eduvod/video") @CrossOrigin public class VodController { @Autowired private VodService vodService; //上传视频到阿里云 @PostMapping("uploadAlyiVideo") public R uploadAlyiVideo(MultipartFile file) { String videoId = vodService.uploadVideoAly(file); return R.ok().data("videoId",videoId); } }
VodService接口
public interface VodService { String uploadVideoAly(MultipartFile file); }
VodServiceImpl实现类
@Service public class VodServiceImpl implements VodService { @Override public String uploadVideoAly(MultipartFile file) { try { //fileName:上传文件原始名称 String fileName = file.getOriginalFilename(); //title:上传之后显示的名称 String title = fileName.substring(0, fileName.lastIndexOf(".")); //inputStream:上传文件输入流 InputStream inputStream = file.getInputStream(); UploadStreamRequest request = new UploadStreamRequest(ConstantVodUtils.ACCESS_KEY_ID, ConstantVodUtils.ACCESS_KEY_SECRET, title, fileName, inputStream); UploadVideoImpl uploader = new UploadVideoImpl(); UploadStreamResponse response = uploader.uploadStream(request); String videoId = null; if (response.isSuccess()) { videoId = response.getVideoId(); } else { //如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因 System.out.print("VideoId=" + response.getVideoId() + "\n"); System.out.print("ErrorCode=" + response.getCode() + "\n"); System.out.print("ErrorMessage=" + response.getMessage() + "\n"); videoId = response.getVideoId(); } System.out.println("000000"+videoId); return videoId; } catch(Exception e) { e.printStackTrace(); return null; } } }
注意:需要在修改nginx配置文件nginx.conf,加入接口地址:
location ~ /vod/ { proxy_pass http://localhost:8003; }
配置nginx上传文件大小,否则上传时会有 413 (Request Entity Too Large) 异常
打开nginx主配置文件nginx.conf,找到http{},添加
client_max_body_size 1024m;
重启nginx
nginx -s reload
四、添加小节-上传视频功能(前端)
1、在chapter.vue页面的添加小节弹框的上传视频处添加上传组件代码
<el-form-item label="上传视频"> <el-upload :on-success="handleVodUploadSuccess" :on-remove="handleVodRemove" :before-remove="beforeVodRemove" :on-exceed="handleUploadExceed" :file-list="fileList" :action="BASE_API+'/eduvod/video/uploadAlyiVideo/'" :limit="1" class="upload-demo"> <el-button size="small" type="primary">上传视频</el-button> <el-tooltip placement="right-end"> <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>
2、前端方法定义
//上传视频成功调用的方法 handleVodUploadSuccess(response, file, fileList) { //上传视频id赋值 this.video.videoSourceId = response.data.videoId //上传视频名称赋值 this.video.videoOriginalName = file.name }, //试图上传多于一个视频 handleUploadExceed(files, fileList) { this.$message.warning('想要重新上传视频,请先删除已上传的视频') }
五、添加小节--删除云端视频
1、后端
①service
接口
void removeVideo(String videoId);
实现
@Override public void removeVideo(String videoId) { try{ DefaultAcsClient client = AliyunVodSDKUtils.initVodClient( ConstantPropertiesUtil.ACCESS_KEY_ID, ConstantPropertiesUtil.ACCESS_KEY_SECRET); DeleteVideoRequest request = new DeleteVideoRequest(); request.setVideoIds(videoId); DeleteVideoResponse response = client.getAcsResponse(request); System.out.print("RequestId = " + response.getRequestId() + "\n"); }catch (ClientException e){ throw new GuliException(20001, "视频删除失败"); } }
②controller
@DeleteMapping("{videoId}") public R removeVideo(@ApiParam(name = "videoId", value = "云端视频id", required = true) @PathVariable String videoId){ videoService.removeVideo(videoId); return R.ok().message("视频删除成功"); }
2、前端
①定义api
api/edu/vod.js
import request from '@/utils/request' const api_name = '/admin/vod/video' export default { removeById(id) { return request({ url: `${api_name}/${id}`, method: 'delete' }) } }
②组件方法
views/edu/course/chapter.vue
import vod from '@/api/edu/vod' beforeVodRemove(file, fileList) { return this.$confirm(`确定移除 ${file.name}?`) }, handleVodRemove(file, fileList) { console.log(file) vod.removeById(this.video.videoSourceId).then(response=>{ this.$message({ type: 'success', message: response.message }) }) },
六、视频文件回显
一、数据库优化冗余字段
1、video表中添加一列
video_original_name varchar 100 原始文件名称
2、pojo中定义新增字段
EduVideo.java
@ApiModelProperty(value = "云服务器上存储的视频文件名称") private String videoOriginalName;
二、前端修改
1、chapter.vue
添加videoOriginalName的数据定义
video: {// 课时对象 title: '', sort: 0, free: false, videoSourceId: '', videoOriginalName: '' },
2、上传成功回调
添加对videoOriginalName的赋值
handleVodUploadSuccess(response, file, fileList) { this.video.videoSourceId = response.data.videoId this.video.videoOriginalName = file.name; },
3、修改回调Video
editVideo(videoId) { this.dialogVideoFormVisible = true video.getVideoInfoById(videoId).then(response => { this.video = response.data.item this.fileList = [{'name': this.video.videoOriginalName}] }) },
4、删除云端video回调
handleVodRemove(file, fileList) { console.log(file) vod.removeById(this.video.videoSourceId).then(response => { this.video.videoSourceId = '' this.video.videoOriginalName = '' this.fileList = [] this.$message({ type: 'success', message: response.message }) }) },