将视频文件转码为视频编码为H264并且音频编码为ACC的视频,并上传至资源服务器。

应用场景 : 三方摄像头厂商云视频只会短时间保留,如需长时间保留则需转储至自己的资源服务器。
解决案例 : 保存海康的视频成MP4格式的视频,最后无法在网页上播放,或者干脆本地无法打开。

引入pom依赖

      <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.5.7</version>
        </dependency>

视频转码核心代码,转码成功后会在同级目录下生成转码后的视频

    /**
     * 将视频文件转码为视频编码为H264并且音频编码为ACC的视频
     * @param absolutePath 视频文件路径
     * @param format 转码后的封装格式
     * @return
     * @throws Exception
     */
    public  String convert(String absolutePath, String format) throws Exception {
        String path = absolutePath;
        FFmpegFrameGrabber frameGrabber = FFmpegFrameGrabber.createDefault(path);
        String fileName = null;
        Frame capturedFrame = null;
        FFmpegFrameRecorder recorder = null;
        try {
            int index = path.lastIndexOf(".");
            if (index < 0) {
                index += path.length();
            }
            fileName = path.replace(path.substring(index), "_recode." + format);
            frameGrabber.start();
            recorder = new FFmpegFrameRecorder(fileName, frameGrabber.getImageWidth(), frameGrabber.getImageHeight(), frameGrabber.getAudioChannels());
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
            recorder.setFormat(format);
            recorder.setFrameRate(frameGrabber.getFrameRate());
            recorder.setVideoBitrate(frameGrabber.getVideoBitrate());
            recorder.setAspectRatio(frameGrabber.getAspectRatio());
            recorder.setAudioBitrate(frameGrabber.getAudioBitrate());
            recorder.setAudioOptions(frameGrabber.getAudioOptions());
            recorder.setSampleRate(frameGrabber.getSampleRate());
            recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
            recorder.start();

            while (true) {
                capturedFrame = frameGrabber.grabFrame();

                if (capturedFrame == null) {
                    log.info(fileName + "转码完成");
                    break;
                }
                recorder.record(capturedFrame);
            }
        } finally {
            if (recorder != null) {
                try {
                    recorder.close();
                } catch (Exception e) {
                    log.warn("recorder.close异常", e);
                }
            }
            try {
                frameGrabber.close();
            } catch (org.bytedeco.javacv.FrameGrabber.Exception e) {
                log.warn("frameGrabber.close异常", e);
            }
        }
        return fileName;
    }

处理视频转码,转码后上传资源服务器,删除中转资源

    public void upload(String url) {
         // url = "https://open.ys7.com/api/lapp/mq/downloadurl?appKey=14356cdcd2da4703b2db05ae56e7420f&fileKey=ISAPI_FILES/K27765188_1/20221209113342970-K27765188-1-10000-2$encrypt=2,2022-12-09T11:33:46,434e6d9f142facfc6b678c1b21430be5";
        try {
            MultipartFile multipartFile = getFile(url, "test.mp4");
            // 获取文件的名称
            String originalFilename = multipartFile.getOriginalFilename();
            // 文件后缀 例如:.png
            String fileSuffix = originalFilename.substring(originalFilename.lastIndexOf("."));
            // uuid 生成文件名
            String uuid = String.valueOf(UUID.randomUUID());
            // 根路径,在 resources/static/upload
            String basePath = ResourceUtils.getURL("classpath:").getPath() + "upload/";
            // 新的文件名,使用uuid生成文件名
            String fileName = uuid + fileSuffix;
            // 创建新的文件
            File fileExist = new File(basePath);
            // 文件夹不存在,则新建
            if (!fileExist.exists()) {
                fileExist.mkdirs();
            }
            // 获取文件对象
            File file = new File(basePath, fileName);
            // 完成文件的上传
            multipartFile.transferTo(file);
            String substring = basePath.substring(basePath.indexOf("/") + 1);
            log.info("basePath:{}", substring + fileName);
            String mp4 = convert(substring + fileName, "mp4");
            // 上传转码后的mp4文件
            InputStream inStream = Files.newInputStream(Paths.get(mp4));
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100];
            int rc = 0;
            while ((rc = inStream.read(buff, 0, 100)) > 0) {
                swapStream.write(buff, 0, rc);
            }
            byte[] in2b = swapStream.toByteArray();
            BytesToMultipartFile toMultipartFile = new BytesToMultipartFile(in2b, "file", fileName, MediaType.MULTIPART_FORM_DATA);
            R<BladeFile> picFileR = ossClient.feignPutFileAttach(toMultipartFile, InvoiceConstant.ATTACH_TYPE, InvoiceConstant.FILE_PIC_URL + fileName, IdWorker.getId());
            System.out.println("picFileR:"+picFileR.getData().getLink());
            // 处理完毕删除文件
            deleteFolders(substring);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

删除文件下所有文件,为避免并发操作,此处可以优化为删除指定文件

    public void deleteFolders(String filePath) {
        Path path = Paths.get(filePath);
        try {
            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException {
                    Files.delete(file);
                    log.info("删除文件: {}", file);
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇