视频格式网络地址转换视频到本地,获取封面、时长,其他格式转换成mp4

使用ffmpeg软件转换网络视频,先从官网下载对应操作系统环境的包

注意:网络地址需要是视频格式结尾,例如.mp4,.flv 等

官网地址:Download FFmpeg     

window包:

415b5111089d42a4a02116b3fb877065.png

linux包:

39729fa04ffc4bf895ce22971e583292.png

如果下载缓慢,下载迅雷安装使用下载。

解压缩后对应截图:

window:

4cc5ed2dd51f4e6f9c96cb846d54e438.png

linux:

16eb35142ad44511b8c0089bd9437a56.png

在maven项目的pom.xml引入依赖包:

 <dependency>
                <groupId>net.bramp.ffmpeg</groupId>
                <artifactId>ffmpeg</artifactId>
                <version>0.7.0</version>
            </dependency>
 <dependency>
                <groupId>org.bytedeco</groupId>
                <artifactId>javacpp</artifactId>
                <version>1.4.1</version>
            </dependency>
            <dependency>
                <groupId>org.bytedeco</groupId>
                <artifactId>javacv</artifactId>
                <version>1.4.1</version>
            </dependency>
            <dependency>
                <groupId>org.bytedeco.javacpp-presets</groupId>
                <artifactId>ffmpeg-platform</artifactId>
                <version>3.4.2-1.4.1</version>
            </dependency>

引入类:

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import net.bramp.ffmpeg.FFmpeg;
import net.bramp.ffmpeg.FFmpegExecutor;
import net.bramp.ffmpeg.FFprobe;
import net.bramp.ffmpeg.builder.FFmpegBuilder;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

网络地址转换成本地视频方法:

 /**
     * 视频链接转换成本地视频
     * @param videoUrl
     * @param downloadPath
     * @return
     */
    public static boolean downVideo(String videoUrl,String downloadPath){
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        RandomAccessFile randomAccessFile = null;
        boolean re;
        try{
            URL url = new URL(videoUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestProperty("Range","bytes=0-");
            connection.connect();
            if (connection.getResponseCode() / 100 != 2){
                System.out.println("链接失败");
                return  false;
            }
            inputStream = connection.getInputStream();
            int downloaded = 0;
            int fileSize = connection.getContentLength();
            randomAccessFile = new RandomAccessFile(downloadPath,"rw");
            while (downloaded < fileSize){
                byte[] buffer = null;
                if (fileSize - downloaded >= 1000000){
                    buffer = new byte[1000000];
                }else{
                    buffer = new byte[fileSize - downloaded];
                }
                int read = -1;
                int currentDownload = 0;
                while (currentDownload < buffer.length){
                    read = inputStream.read();
                    buffer[currentDownload++] = (byte) read;
                }
                randomAccessFile.write(buffer);
                downloaded += currentDownload;
            }
            re = true;
            return re;
        } catch (Exception e) {
            e.printStackTrace();
            re = false;
            return re;
        }finally {
            try{
                connection.disconnect();
                inputStream.close();
                randomAccessFile.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

网站地址转换成本地视频后,再转换成mp4视频方法:

/**
     * 其他视频格式地址转换成mp4
     * @param orginalVideoPath 原视频地址
     * @param newMp4FilePath 新mp4地址
     * @return
     */
    public static boolean otherVideoToMp4(String orginalVideoPath,String newMp4FilePath)  {
        try{
            String ffmpegPath = "";
            String ffprobePath = "";
            if (SystemUtils.isWindows()){
                //目录里放的文件没有提交保存,在本地测试的时候自行添加
                ffmpegPath = VideoCovertUtil.class.getResource("/ffmpegdir/win/bin/ffmpeg.exe").getPath();
                ffprobePath = VideoCovertUtil.class.getResource("/ffmpegdir/win/bin/ffprobe.exe").getPath();
            }else if (SystemUtils.isLinux()){
                /*ffmpegPath = VideoCovertUtil.class.getResource("/ffmpegdir/linux/ffmpeg").getPath();
                ffprobePath = VideoCovertUtil.class.getResource("/ffmpegdir/linux/ffprobe").getPath();*/
                //在linux安装ffmpeg后配置路径
                //安装步骤:https://blog.csdn.net/ysushiwei/article/details/130162831
                ffmpegPath = "/usr/local/bin/ffmpeg";
                ffprobePath = "/usr/local/bin/ffprobe";
            }

            log.info("ffmpegPath:"+ffmpegPath);
            log.info("ffmpegPath:"+ffprobePath);
            FFmpeg fFmpeg = new FFmpeg(ffmpegPath);
            FFprobe fFprobe = new FFprobe(ffprobePath);
            FFmpegBuilder builder = new FFmpegBuilder()
                    .setInput(orginalVideoPath)
                    .addOutput(newMp4FilePath)
                    .done();
            FFmpegExecutor executor = new FFmpegExecutor(fFmpeg,fFprobe);
            executor.createJob(builder).run();
            log.info("执行完毕");
            return  true;
        }catch (IOException e){
            e.printStackTrace();
            return false;
        }
    }

window可以直接放在项目中,但是linux还需要配置。步骤如下。

1、将上方的linux包上传到服务器,解压缩:

tar -xvf ffmpeg-release-amd64-static.tar.xz

2、解压缩后进入根目录分别复制根目录下的ffmpeg和ffprobe到 /usr/local/bin/目录下:

sudo cp 解压缩目录/ffmpeg /usr/local/bin/
sudo cp 解压缩目录/ffprobe /usr/local/bin/

3.还要给文件设置权限,否则运行代码的时候报没有权限:

sudo chmod +x /usr/local/bin/ffmpeg

sudo chmod +x /usr/local/bin/ffprobe

4、最后检查是否配置成功,如果有内容输出来则成功:

ffmpeg -version

ffprobe -version

linux环境配置好后,即可正常解析.

从视频中提取封面和获取时长:

 /**
     * 获取视频的第一帧封面
     * @param filePath 视频地址
     * @param targetPath 视频封面地址
     */
    public static void getCover(String filePath,String targetPath){
        try{
            // 视频地址
            FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(new File(filePath));

            grabber.start();

            Java2DFrameConverter converter = new Java2DFrameConverter();

            BufferedImage image = converter.convert(grabber.grabImage());
            // 本地图片保存地址
            ImageIO.write(image, "png", new File(targetPath));

            grabber.stop();
            image.flush();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * 使用FFmpeg获取视频时长
     *
     * @param path 视频文件地址
     * @return 时长,单位为秒
     * @throws IOException
     */
    public static String getDuration(String path) {
        // 读取视频文件
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(path);
        try {
            grabber.start();
        } catch (FrameGrabber.Exception e) {
            e.printStackTrace();
        }
        // 获取视频长度(单位:秒)
        int duration = grabber.getLengthInFrames() / (int) grabber.getFrameRate();
        try {
            grabber.stop();
        } catch (FrameGrabber.Exception e) {
            e.printStackTrace();
        }
        return DateUtil.secondToTime(duration);
    }

由于视频转换下载等速度比较慢,推荐使用异步执行。我用的是若依的框架,代码如下。如用其他框架,可自行参考写异步操作

//异步执行方法。不会等待执行完才执行下一位
AsyncManager.me().execute(AsyncFactory.convertVideoNetUrl(video.getVideoPath(),video.getId(),
                Constants.CONVERT_VIDEO_NET_VIDEO_URL));

#在AsyncManager类里自定义一个异步方法如下

 /**
     * 
     * @param videNetUrl 视频网络地址
     * @param id 类id
     * @param entityClazz 类 0:视频 1:文章
     * @return 任务task
     */
    public static TimerTask convertVideoNetUrl(final String videNetUrl,Long id,Integer entityClazz)
    {
        return new TimerTask()
        {
            @Override
            public void run()
            {
                if (entityClazz == null || id == null || StrUtil.isBlank(videNetUrl)){
                    return;
                }
                if (entityClazz == 0){
                    IVideoService videoService =  SpringUtils.getBean(IVideoService.class);
                    Video video = videoService.selectVideoById(id);
                    if (video == null){
                        return;
                    }
                    //现在是上传视频地址
                    //先转换视频地址到服务器
                    //后缀
                    String ext = video.getVideoPath().substring(video.getVideoPath().lastIndexOf("."));
                    String videosubpath = StringUtils.format("{}/{}_{}{}", DateUtils.datePath(),
                            IdUtils.fastSimpleUUID(), Seq.getId(Seq.uploadSeqType), ext);
                    String downloadPath = null;
                    try {
                        downloadPath = FileUploadUtils.getAbsoluteFile(HqaConfig.getUploadPath() + "/", videosubpath).getAbsolutePath();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    boolean downVideo = VideoCovertUtil.downVideo(video.getVideoPath(),downloadPath);
                    if (downVideo && StrUtil.isNotBlank(downloadPath) && downloadPath != null){
                        if (!ext.contains("mp4")){
                            //下载成功后如果不是mp4格式,转换成mp4格式
                            String newVideosubpath = StringUtils.format("{}/{}_{}{}", DateUtils.datePath(),
                                    IdUtils.fastSimpleUUID(), Seq.getId(Seq.uploadSeqType), ".mp4");
                            String newMp4FilePath = null;
                            try {
                                newMp4FilePath = FileUploadUtils.getAbsoluteFile(HqaConfig.getUploadPath() + "/", newVideosubpath).getAbsolutePath();
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                            boolean toMp4 = VideoCovertUtil.otherVideoToMp4(downloadPath,newMp4FilePath);
                            if (toMp4 && StrUtil.isNotBlank(newMp4FilePath) && newMp4FilePath != null){
                                //转换成功后删除之前下载过的视频地址,并且保存新的mp4地址
                                if (new File(downloadPath).exists()){
                                    FileUtils.deleteFile(downloadPath);
                                }
                                if (newMp4FilePath.contains("\\")){
                                    newMp4FilePath = newMp4FilePath.replace("\\","/");
                                }
                                String newPath = newMp4FilePath.replace(HqaConfig.getProfile(),"/profile");
                                video.setVideoPath(newPath);
                            }
                        }else{
                            if (downloadPath.contains("\\")){
                                downloadPath = downloadPath.replace("\\","/");
                            }
                            //保存地址
                            String newPath = downloadPath.replace(HqaConfig.getProfile(),"/profile");
                            video.setVideoPath(newPath);
                        }
                        //视频截图和时长
                        //获取视频第一帧封面
                        String parentPath = HqaConfig.getUploadPath()+"/"+ DateUtils.datePath();
                        String fileName = IdUtils.fastSimpleUUID()+".png";
                        String targetPath = parentPath+"/"+ fileName;
                        try {
                            FileUploadUtils.getAbsoluteFile(parentPath,fileName);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        String filePath = video.getVideoPath().replace("/profile","");
                        filePath=HqaConfig.getProfile()+filePath;
                        VideoCovertUtil.getCover(filePath,targetPath);
                        video.setCover(targetPath.replace(HqaConfig.getProfile(),"/profile"));
                        String  duration = VideoCovertUtil.getDuration(filePath);
                        video.setDuration(duration);
                        videoService.updateVideo(video);
                    }
                }else if (entityClazz == 1){
                    IArticleService articleService = SpringUtils.getBean(IArticleService.class);
                    Article article = articleService.selectArticleById(id);
                    if (article == null){
                        return;
                    }
                    //现在是上传视频地址
                    //先转换视频地址到服务器
                    //后缀
                    String ext = article.getVideoPath().substring(article.getVideoPath().lastIndexOf("."));
                    String videosubpath = StringUtils.format("{}/{}_{}{}", DateUtils.datePath(),
                            IdUtils.fastSimpleUUID(), Seq.getId(Seq.uploadSeqType), ext);
                    String downloadPath = null;
                    try {
                        downloadPath = FileUploadUtils.getAbsoluteFile(HqaConfig.getUploadPath() + "/", videosubpath).getAbsolutePath();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    boolean downVideo = VideoCovertUtil.downVideo(article.getVideoPath(),downloadPath);
                    if (downVideo && StrUtil.isNotBlank(downloadPath) && downloadPath != null){
                        if (!ext.contains("mp4")){
                            //下载成功后如果不是mp4格式,转换成mp4格式
                            String newVideosubpath = StringUtils.format("{}/{}_{}{}", DateUtils.datePath(),
                                    IdUtils.fastSimpleUUID(), Seq.getId(Seq.uploadSeqType), ".mp4");
                            String newMp4FilePath = null;
                            try {
                                newMp4FilePath = FileUploadUtils.getAbsoluteFile(HqaConfig.getUploadPath() + "/", newVideosubpath).getAbsolutePath();
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                            boolean toMp4 = VideoCovertUtil.otherVideoToMp4(downloadPath,newMp4FilePath);
                            if (toMp4 && StrUtil.isNotBlank(newMp4FilePath) && newMp4FilePath != null){
                                //转换成功后删除之前下载过的视频地址,并且保存新的mp4地址
                                if (new File(downloadPath).exists()){
                                    FileUtils.deleteFile(downloadPath);
                                }
                                if (newMp4FilePath.contains("\\")){
                                    newMp4FilePath = newMp4FilePath.replace("\\","/");
                                }
                                String newPath = newMp4FilePath.replace(HqaConfig.getProfile(),"/profile");
                                article.setVideoPath(newPath);
                            }
                        }else{
                            if (downloadPath.contains("\\")){
                                downloadPath = downloadPath.replace("\\","/");
                            }
                            //保存地址
                            String newPath = downloadPath.replace(HqaConfig.getProfile(),"/profile");
                            article.setVideoPath(newPath);
                        }
                        articleService.updateArticle(article);
                    }
                }
            }
        };
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/274351.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

干掉程序员饭碗的会是 AI 吗?

你好&#xff0c;我是坚持分享干货的 EarlGrey&#xff0c;翻译出版过《Python编程无师自通》、《Python并行计算手册》等技术书籍。 如果我的分享对你有帮助&#xff0c;请关注我&#xff0c;一起向上进击。 创作不易&#xff0c;希望大家给一点鼓励&#xff0c;把公众号设置为…

0.1+0.2≠0.3,揭秘Python自带的Bug

朋友们&#xff0c;问一个简单的问题&#xff1a;0.10.2&#xff1f; 你肯定会说&#xff1a;中国人不骗中国人&#xff0c;0.10.20.3。 但是在Python里&#xff0c;0.10.2≠0.3 &#xff0c;我们今天一起来看看这个&#xff0c;并且看一下解决办法。 离奇的错误 在python里…

【C语言】自定义类型:结构体深入解析(三)结构体实现位段最终篇

文章目录 &#x1f4dd;前言&#x1f320;什么是位段&#xff1f;&#x1f309; 位段的内存分配&#x1f309;VS怎么开辟位段空间呢&#xff1f;&#x1f309;位段的跨平台问题&#x1f320; 位段的应⽤&#x1f320;位段使⽤的注意事项&#x1f6a9;总结 &#x1f4dd;前言 本…

内网离线搭建之----kafka-manager集群监控

工具介绍: 为了简化开发者和服务工程师维护Kafka集群的工作&#xff0c;yahoo构建了一个叫做Kafka管理器的基于Web工具&#xff0c;叫做 Kafka Manager。 这个管理工具可以很容易地发现分布在集群中的哪些topic分布不均匀&#xff0c;或者是分区在整个集群分布不均匀的的情况…

mfc140u.dll丢失的解决方法,怎样修复mfc140u.dll

最近看到很多朋友在问找不到mfc140u.dll丢失怎么办&#xff1f;有什么解决方法&#xff0c;今天就给小伙伴们解答一下&#xff0c;mfc140u.dll丢失的解决办法&#xff0c;怎么修复mfc140u.dll。 一.丢失的原因 1.损坏的程序安装:在安装某个程序时&#xff0c;可能会出现意外中…

Python算法例30 统计前面比自己小的数

1. 问题描述 给定一个整数数组&#xff08;数组大小为n&#xff0c;元素的取值范围为0~10000&#xff09;&#xff0c;对于数组中的每个元素&#xff0c;计算其前面元素中比它小的元素数量。 2. 问题示例 对于数组[1&#xff0c;2&#xff0c;7&#xff0c;8&#xff0c;5]&…

Oracle database 静默安装 oracle12c 一键安装 12.1.0.2

基于oracle安装包中应答文件实现一键安装 注意此安装脚本基于12.1.0.2 安装包 原始安装包结构为两个压缩包 此脚本使用安装包为原始压缩包解压后、 重新封装为一个.zip压缩包 建议在linux 环境下解压重新压缩后 使用该脚本 支持环境: Linux :centerOS 7 oracle :12.1.0.…

Android原生实现分段选择

六年前写的一个控件&#xff0c;一直没有时间总结&#xff0c;趁年底不怎么忙&#xff0c;整理一下之前写过的组件。供大家一起参考学习。废话不多说&#xff0c;先上图。 一、效果图 实现思路使用的是radioGroup加radiobutton组合方式。原理就是通过修改RadioButton 的backgr…

Langchain访问OpenAI ChatGPT API Account deactivated的另类方法,访问跳板机API

笔者曾经写过 ChatGPT OpenAI API请求限制 尝试解决 Account deactivated. Please contact us through our help center at help.openai.com if you need assistance. 结果如何&#xff1f; 没有啥用。目前发现一条曲线救国的方案。 1. 在官方 openai 库中使用 此处为最新Op…

【数据结构和算法】寻找数组的中心下标

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 前缀和的解题模板 2.1.1 最长递增子序列长度 2.1.2 寻找数组中第 k 大的元素 2.1.3 最长公共子序列…

模拟算法 蓝桥杯备赛系列 acwing

文章目录&#xff1a; 基础知识 什么是模拟&#xff1f; 例题 一、错误票据 1.解题思路 2.代码 二、移动距离 1.解题思路 2.代码 三、航班时间 1.解题思路 2.代码 四、外卖优先级 1.解题思路 2.代码 前面为了目录好看大家就当个玩笑看吧哈哈哈。下面上正文。 正文 基础知识 什…

Amazon CodeWhisperer 免费 AI 代码生成助手体验分享

今年上半年&#xff0c;亚马逊云科技正式推出了实时AI编程助手 Amazon CodeWhisperer&#xff0c;还提供了供所有开发人员免费使用的个人版版本。经过一段时间的体验&#xff0c;我觉得 CodeWhisperer 可以处理编程工作中遇到的很多问题&#xff0c;并且帮助开发人员提高编程效…

websocket 介绍

目录 1&#xff0c;前端如何实现即时通讯短轮询长轮询 2&#xff0c;websocket2.1&#xff0c;握手2.2&#xff0c;握手过程举例2.3&#xff0c;socket.io 3&#xff0c;websocket 对比 http 的优势 1&#xff0c;前端如何实现即时通讯 在 websocket 协议出现之前&#xff0c;…

Ubuntu20.04服务器使用教程(安装教程、常用命令、故障排查)持续更新中.....

安装教程&#xff08;系统、驱动、CUDA、CUDNN、Pytorch、Timeshift、ToDesk&#xff09; 制作U盘启动盘&#xff0c;并安装系统 在MSDN i tell you下载Ubuntu20.04 Desktop 版本&#xff0c;并使用Rufus制作UEFI启动盘&#xff0c;参考UEFI安装Ubuntu使用GPTUEFI模式安装&am…

hql、数据仓库、sql调优、hive sql、python

SQL/HQL HQL(Hibernate Query Language) 是面向对象的查询语言 SQL的操作对象是数据列、表等数据库数据 ; 而HQL操作的是类、实例、属性 #FROM String hql "from com.demo.bean.User" "select * from user" #WHERE "form User u where u.id 1…

Filter过滤器的使用!!!

什么是过滤器 当浏览器向服务器发送请求的时候&#xff0c;过滤器可以将请求拦截下来&#xff0c;完成一些特殊的功能&#xff0c;比如&#xff1a;编码设置、权限校验、日志记录等。 过滤器执行流程 过滤器的使用&#xff1a; /** Copyright (c) 2020, 2023, All rights …

【AIGC】AIGC——真正意义的智能,颠覆性的变革

AIGC——真正意义的智能&#xff0c;颠覆性的变革 AIGC&#xff08;AI Generated Content&#xff0c;即人工智能生成的内容&#xff09;可以通过以下几个方面来实现跨越&#xff1a; 技术跨越&#xff1a;AIGC可以通过不断的技术创新和进步&#xff0c;实现从简单的生成内容…

电脑键盘大小写切换按哪个键?正确操作分享!

“我在工作时&#xff0c;经常需要输入英文文档&#xff0c;但我不知道输入大小字母时应该按哪个键切换&#xff0c;有朋友可以教教我吗&#xff1f;” 在我们使用电脑时&#xff0c;输入英文文档是经常会遇到的事。当输入某些单词时&#xff0c;我们可能需要切换大小写。电脑键…

ASUS华硕ROG幻16 2023款GU603VU VV VI笔记本电脑原厂Win11.22H2系统

链接&#xff1a;https://pan.baidu.com/s/1AgevUZleCHBJgCBcIp5CFQ?pwdhjxy 提取码&#xff1a;hjxy 华硕笔记本2023款幻16原厂Windows11系统自带所有驱动、出厂主题壁纸、Office办公软件、MyASUS华硕电脑管家、Armoury Crate奥创控制中心等预装程序 文件格式&#xff1…

Centos开启防火墙和端口命令

Centos开启防火墙和端口命令 1 课堂小知识1.1 centos7简介1.2 iptables方式开启防火墙 2 操作步骤2.1 开启查看关闭firewalld服务状态2.2 查看端口是否开放2.3 新增开放端口2.4 查看开放的端口 3 防火墙的其他指令 1 课堂小知识 1.1 centos7简介 CentOS 7是CentOS项目发布的开…