【开发指南】Spring Cloud集成阿里云VOD构建视频服务

528 阅读3分钟

环境搭建

  1. 一般情况下,项目会单独创建一个vod视频服务,来对视频进行相关操作。

  2. 配置aliyun基础环境,获取AccessKey和AccessKey Secret。(详见《Spring Cloud集成阿里云OSS完成头像上传功能》)

  3. 下载并安装jar包

    如果要实现上传视频,则需要aliyun-java-vod-upload-1.4.5.jar

    因为aliyun-java-vod-upload-1.4.5.jar还未正式开源,所以需要单独下载并安装到Maven本地仓库。

    在下载完jar包的文件目录下打开命令行输入:

    mvn install:install-file -DgroupId=com.aliyun -DartifactId=aliyun-sdk-vod-upload -Dversion=1.4.5 -Dpackaging=jar -Dfile=aliyun-java-vod-upload-1.4.5.jar
    

    注意:

    如果命令运行不了,说明Maven没有下载或者Maven没有配置环境变量,使用:mvn -v 测试命令行是否能够执行Maven命令。

  4. pom.xml中引入相关依赖

    <dependencies>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-vod</artifactId>
            <version>2.15.11</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-sdk-vod-upload</artifactId>
            <version>1.4.5</version>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20170516</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.69</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.2</version>
        </dependency>
    </dependencies>
    
    <!--  阿里云Vod服务jar包的仓库 -->
    <repositories>
        <repository>
            <id>sonatype-nexus-staging</id>
            <name>Sonatype Nexus Staging</name>
            <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
    
  5. 配置application.yml

    spring:
      ...
      # 文件上传配置
      servlet:
        multipart:
          # 单个视频文件限制1GB以内
          max-file-size: 1024MB
          max-request-size: 1024MB
    
    # 阿里云Vod
    aliyun:
      vod:
        file:
          keyid: xxxxxxxxxxxxxx
          keysecret: xxxxxxxxxxxxxxxxxxxxxxx
    
  6. 创建常量类

    @Component
    public class ConstantPropertiesUtils implements InitializingBean {
    
        @Value("${aliyun.vod.file.keyid}")
        private String keyId;
    
        @Value("${aliyun.vod.file.keysecret}")
        private String keySecret;
    
        public static String ACCESS_KEY_ID;
        public static String ACCESS_KEY_SECRET;
    
        // 当读取application.yml时,自动给两个常量赋值
        @Override
        public void afterPropertiesSet() throws Exception {
            ACCESS_KEY_ID = keyId;
            ACCESS_KEY_SECRET = keySecret;
        }
    }
    

    注意:该类变量读取的配置信息,默认是从application.yml或者配置中心(Nacos,Spring Cloud Config)已经设置的配置文件中读取,如果不是上述配置文件,在类上配置注解指定配置文件即可。

    @PropertySource("classpath:xxx.yml")
    
  7. 创建阿里云SDK工具类

    @Component
    public class AliyunVodSDKUtils {
    
        // 初始化Vod客户端调用对象
        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);
    
            // SDK的调用依赖client对象
            return client;
        }
    
        public static DefaultAcsClient initVodClient() throws ClientException {
            return initVodClient(ConstantPropertiesUtils.ACCESS_KEY_ID, ConstantPropertiesUtils.ACCESS_KEY_SECRET);
        }
    
        /**
         * 获取播放地址
         * @param videoId 视频ID
         * @return GetPlayInfoResponse 获取视频播放响应数据
         * @throws Exception
         */
        public static GetPlayInfoResponse getPlayInfo(String videoId) throws Exception {
            // 创建发送请求客户端
            DefaultAcsClient client = initVodClient();
    
            GetPlayInfoRequest request = new GetPlayInfoRequest();
            request.setVideoId(videoId);
    
            return client.getAcsResponse(request);
        }
    
        /**
         * 获取视频信息
         * @param videoId 视频ID
         * @return GetVideoInfoResponse 获取视频信息响应数据
         * @throws Exception
         */
        public static GetVideoInfoResponse getVideoInfo(String videoId) throws Exception {
            // 创建发送请求客户端
            DefaultAcsClient client = initVodClient();
    
            GetVideoInfoRequest request = new GetVideoInfoRequest();
            request.setVideoId(videoId);
    
            return client.getAcsResponse(request);
        }
    
        /**
         * 获取媒资信息
         * @param pageNo 当前页号
         * @param pageSize 每页容量
         * @return SearchMediaResponse 查询媒资信息响应数据
         * @throws ClientException
         */
        public static SearchMediaResponse searchMedia(int pageNo, int pageSize) throws ClientException {
            // 创建发送请求客户端
            DefaultAcsClient client = initVodClient();
    
            SearchMediaRequest request = new SearchMediaRequest();
            request.setFields("Title,CoverURL,Status");
            request.setPageNo(pageNo);
            request.setPageSize(pageSize);
            request.setSearchType("video");
            request.setSortBy("CreationTime:Desc");
    
            return client.getAcsResponse(request);
        }
    
        /**
         * 删除视频
         * @param videoIds 支持传入多个视频ID,多个用逗号分隔
         * @return DeleteVideoResponse 删除视频响应数据
         * @throws Exception
         */
        public static DeleteVideoResponse deleteVideo(String videoIds) throws Exception {
            // 创建发送请求客户端
            DefaultAcsClient client = initVodClient();
    
            DeleteVideoRequest request = new DeleteVideoRequest();
            request.setVideoIds(videoIds);
    
            return client.getAcsResponse(request);
        }
    
    }
    

    常用方法封装(Service层)

    1. 上传视频

    public String uploadVideo(MultipartFile video) {
        String videoId = null;
    
        try {
            String fileName = video.getOriginalFilename();
            String title = fileName.substring(0, fileName.lastIndexOf('.'));
            InputStream inputStream = video.getInputStream();
    
            // 创建请求对象
            UploadStreamRequest request = new UploadStreamRequest(
                ConstantPropertiesUtils.ACCESS_KEY_ID,
                ConstantPropertiesUtils.ACCESS_KEY_SECRET,
                title, fileName, inputStream);
    
            // 创建文件上传器
            UploadVideoImpl uploader = new UploadVideoImpl();
    
            // 执行文件上传
            UploadStreamResponse response = uploader.uploadStream(request);
            videoId = response.getVideoId();
        } catch (IOException e) {
            throw new VideoUploadException(ResponseEnum.VIDEO_UPLOAD_ERROR);
        }
    
        // 如果上传成功,返回该视频的videoId
        return videoId;
    }
    

    2. 删除视频

    public boolean deleteVideo(String videoId) {
        try {
            AliyunVodSDKUtils.deleteVideo(videoId);
        } catch (Exception e) {
            throw new VideoDeleteException(ResponseEnum.VIDEO_DELETE_ERROR);
        }
    
        return true;
    }
    

    3. 获取视频播放地址

    public String getVideoPlayUrl(String videoId) {
        String playUrl = null;
    
        try {
            GetPlayInfoResponse response = AliyunVodSDKUtils.getPlayInfo(videoId);
            List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList();
    
            // 获取播放地址
            for (GetPlayInfoResponse.PlayInfo playInfo : playInfoList) {
                playUrl = playInfo.getPlayURL();
            }
    
        } catch (Exception e) {
            e.printStackTrace();
        }
    
        return playUrl;
    }
    

    4. 获取视频封面地址

    public String getVideoCoverUrl(String videoId) {
        String coverUrl = null;
        
        try {
            DefaultAcsClient client = AliyunVodSDKUtils.initVodClient();
            GetVideoInfoResponse response = AliyunVodSDKUtils.getVideoInfo(client, videoId);
            
            // 获取封面地址
            coverUrl = response.getVideo().getCoverURL();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return coverUrl;
    }
    

    5. 分页获取视频列表

    public Map<String, Object> videoList(int pageNo, int pageSize) {
        Map<String, Object> videoMap = new HashMap<>();
        List<VideoVo> videoList = new ArrayList<>();
        
        try {
            SearchMediaResponse response = AliyunVodSDKUtils.searchMedia(pageNo, pageSize);
            
            if (response.getMediaList() != null && response.getMediaList().size() > 0) {
                videoMap.put("total", response.getTotal());
                
                for (SearchMediaResponse.Media media : response.getMediaList()) {
                    // 封装视频响应对象
                    VideoVo videoVo = new VideoVo();
                    
                    // 获取aliyun上的视频信息
                    String videoId = media.getVideo().getVideoId();
                    videoVo.setCoverUrl(media.getVideo().getCoverURL());
                    videoVo.setPlayUrl(getVideoPlayUrl(videoId));
                    
                    // 获取本地数据库中的视频信息
                    Video video = findVideoByVideoId(videoId);
                    videoVo.setId(video.getId());
                    videoVo.setTitle(video.getTitle());
                    videoVo.setUploader(video.getUploader());
                    videoVo.setLikeCount(video.getLikeCount());
                    videoVo.setCollectCount(video.getCollectCount());
                    videoVo.setPlayCount(video.getPlayCount());
                    videoVo.setGmtCreate(video.getGmtCreate());
                    
                    videoList.add(videoVo);
                }
                videoMap.put("videoList", videoList);
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }
    
        return videoMap;
    }