简介

这章主要是上传视频截帧,公司需求对动态上传需求是OSS上传和截帧(最开始时没有需求,自己用的是FFmpeg 多媒体处理工具截取的),最后因为服务器上没有FFmpeg 工具,导致上传docker报错,失败,最后OSS截取帧数。

一、FFmpeg的使用(需要下载工具)

springboot集成外部ffmpeg springboot ffmpeg_java


解压就行。

Spring Boot整合FFmpeg截取帧数

pom.xml

<!-- 视频获取某一帧的图片 -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.4.3</version>
        </dependency>

        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg-platform</artifactId>
            <version>4.0.2-1.4.3</version>
        </dependency>

Test

@Test
    public void getVideoInfo() {
        try {
            File file = new File("C:\\Users\\lanys\\Desktop\\周报\\21400e3e608358da2d970bd7f69a37f1.mp4");
            FileInputStream fileInputStream = new FileInputStream(file);
            //放入采集器
            FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber(fileInputStream);
            //启动
            fFmpegFrameGrabber.start();
            //截取图片
            Frame frame = fFmpegFrameGrabber.grabImage();
            Java2DFrameConverter java2DFrameConverter = new Java2DFrameConverter();
            BufferedImage bufferedImage = java2DFrameConverter.getBufferedImage(frame);

            //创建一个ByteArrayOutputStream
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            //输出 可以不用
            ImageIO.write(bufferedImage, "jpg", os);
            InputStream input = new ByteArrayInputStream(os.toByteArray());
            //InputStream转成MultipartFile
            MultipartFile multipartFile =new MockMultipartFile("file", "file.jpg", "text/plain", input);
            s5(multipartFile);
            fFmpegFrameGrabber.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Autowired
    private OSS ossClient;

    @Autowired
    private AliyunConfig aliyunConfig;


    public void s5(MultipartFile multipartFile){
            //获取图片名称
            String originalFilename = multipartFile.getOriginalFilename();;

               DateTime dateTime = new DateTime();
        String filePath = "uploads/dynamic/pictures/" + dateTime.toString("yyyy") + dateTime.toString("MM") + dateTime.toString("dd") + "/" + System.currentTimeMillis() +
                RandomUtils.nextInt(100, 9999) + "." +
                StringUtils.substringAfterLast(originalFilename, ".");

            System.out.println(filePath);

            try {
                ossClient.putObject(aliyunConfig.getBucket(), filePath, new
                        ByteArrayInputStream(multipartFile.getBytes()));
                log.info("--------视频上传成功--------");
            } catch (Exception e) {
                e.printStackTrace();
                log.info("上传失败");
            }
    }

就是这么简单,例子:截取到的图片

二、OSS视频截帧(收费)

价格也不算贵,1000帧数好像2毛钱(自己测试够用)

Spring Boot整合OSS视频截帧

官方OSS接口:https://help.aliyun.com/document_detail/64555.html整合的话就不说了,一篇文章已经说了,正题
pom.xml

<!--   oss     -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.10.2</version>
        </dependency>

说明,如果是接口,一般都是用 MultipartFile 接收视频或图片。

springboot集成外部ffmpeg springboot ffmpeg_spring boot_02


getPoster方法(生成一个可视化图片)

/**
     * 获取视频截图
     *
     * @param videosPath
     * @return
     * @throws IOException
     */
    public String getPoster(String videosPath) throws IOException {
        // 填写视频文件的完整路径。若视频文件不在Bucket根目录,需携带文件访问路径,例如examplefolder/videotest.mp4。
       String objectName = videosPath;
        // 填写视频文件所在的Bucket名称。
        String bucketName = OssBucketName;
        // 使用精确时间模式截取视频5s处的内容,输出为JPG格式的图片,宽度为1080,高度为1800,图片格式:JPG。
        String style = "video/snapshot,t_500,f_jpg,w_1080,h_1800,f_jpg";
        // 指定过期时间为10分钟。
        Date expiration = new Date(System.currentTimeMillis() + 1000 * 60 * 10);
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET);
        //过期时间必须设置,不然报错提示
        req.setExpiration(expiration);
        req.setProcess(style);
        //获取可视化帧数路径,有过期时间
        URL signedUrl = ossClient.generatePresignedUrl(req);
        System.out.println(signedUrl);
        //获取url的路径,进行真正的OSS存储
        String stream = UploadNetworkStream(OssPrefix + signedUrl.getFile());
        return stream;
    }

uploadNetworkStream(获取上传OSS)

/**
     * 上传网络流
     * @param url
     * @throws IOException
     */
    public String UploadNetworkStream(String url) throws IOException {
        System.out.println(url);
        //随机生成一个图片名
        String Path = RandomUtils.nextInt(100, 9999)+".jpg";
        DateTime dateTime = new DateTime();
        //生成一个真正的图片路径(用于数据库存储)
        String picturePath = "uploads/dynamic/videos/" + dateTime.toString("yyyy") + dateTime.toString("MM") + dateTime.toString("dd") + "/" + System.currentTimeMillis() +"/"+Path;
        // 上传网络流, url指的是生成可视化的路径,获取流
        InputStream inputStream = new URL(url).openStream();
        try{
        //上传 OssBucketName就是yml中桶的名称,picturePath 上传的路径,inputStream流
            ossClient.putObject(OssBucketName, picturePath, inputStream);
            //成功返回路径
            return picturePath;
        }catch (Exception e){
            log.info("-------图片复制失败-------");
            e.printStackTrace();
        }
        return null;
    }

好了,例子:例子图片

总结

好了结束,里面有个坑,picturePath路径前面不用加斜杠,不然会网络错误之类的话和如果是接口,接口是开放,创建用户或动态都需要用,不要最后加个ossClient.shutdown(),之后都懂了。