【开发经验】通过ffmpeg进行视频剪辑

2023-05-16

文章目录

  • 前言
  • 一、视频剪辑
    • 1.1 生成标题
    • 2. 文字和背景图叠加
    • 3、视频切割
    • 4、视频和背景图叠加
    • 结果演示
    • java执行cmd指令
    • 更多ffmepg指令


前言

突然发现抖音有有一些人发布电视剧的精彩片段,并且还获得了很多的点赞。突然发现,原来这样也可以这么多赞。
在这里插入图片描述
发现这种视频可以通过工具直接生成。花不多说,上代码。


一、视频剪辑

1.1 生成标题

通过java生成文字图片,加外描边会更加好看。
示例:

 public static void createImage2(String str, Font font, File outFile,
                                   Integer width, Integer height) throws Exception {
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        BufferedImageGraphicsConfig config = BufferedImageGraphicsConfig.getConfig(bufferedImage);
        bufferedImage =config.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        Graphics g = bufferedImage.getGraphics();
        Graphics2D g2 = (Graphics2D) g;
        FontRenderContext frc = g2.getFontRenderContext();
        TextLayout tl = new TextLayout(str, font, frc);
        //字在页面的位置
        Shape sha = tl.getOutline(AffineTransform.getTranslateInstance(0,250));
        //白边的范围
        g2.setStroke(new BasicStroke(8));
        g2.setColor(Color.RED);
        ((Graphics2D) g).draw(sha);
        g2.setColor(Color.WHITE);
        g2.fill(sha);
        // 输出png图片
        ImageIO.write(bufferedImage, "png", outFile);
    }
  public static void main(String[] args) throws Exception {
        String name= "hello java";
                    createImage2(name, new Font("楷体", Font.BOLD, 150), new File(
                    "E:\\a.png"), 800, 600);
    }

输出图片:
在这里插入图片描述

2. 文字和背景图叠加

D:\tools\ffmpeg\ffmpeg-N-99816-g3da35b7cc7-win64-gpl-shared-vulkan\bin\ffmpeg.exe
-y
-i E:\video\guanlangaoshou\外部封面3.jpg
-i E:\video\guanlangaoshou\bigFont\1-1.png
-filter_complex overlay=220:400
E:\video\guanlangaoshou\fontSize\1-1.png

通过ffmpeg工具即可很轻松的实现文字和背景图的叠加效果

  • -y 如果输出文件存在, 则覆盖。
  • -i 后面跟源文件地址 两个源文件进行叠加。
  • -filter_complex overlay 后面跟的数字是叠加时的位置。
  • 最后是输出文件的位置。

如此可实现:1-1是java生成的,加一个自己喜欢的背景图。叠加即可。
在这里插入图片描述

3、视频切割

将视频按照自己的想法分段。

D:\tools\ffmpeg\ffmpeg-N-99816-g3da35b7cc7-win64-gpl-shared-vulkan\bin\ffmpeg.exe
-y
-ss 00:01:44 -i E:\video\guanlangaoshou\videodeal\13.mp4 -to 00:07:00 E:\video\guanlangaoshou\videosplit\13-1.mp4

  • -ss 开始时间
  • -i 视频地址
  • -to 截止长度,意为开始时间向后切7分钟。
  • 最后是输出位置。

4、视频和背景图叠加

D:\tools\ffmpeg\ffmpeg-N-99816-g3da35b7cc7-win64-gpl-shared-vulkan\bin\ffmpeg.exe -y -i E:\video\guanlangaoshou\videoimage\13-1.png -i E:\video\guanlangaoshou\videosplit\13-1.mp4 -filter_complex overlay=-80:500 E:\video\guanlangaoshou\success\13-1.mp4

视频和背景图叠加和图片叠加一样, 只需要自己控制叠加位置即可。

结果演示

最后即可生成这种按照视频分段后可以上传抖音的短视频。
在这里插入图片描述

java执行cmd指令

另外,使用ffmpeg工具的话,是通过cmd指令调用的。附加cmd调用工具类,直接复制调用即可。
CmdUtil.java:

public class CmdUtil {

	public static String execCmd(String cmd){
		BufferedReader bReader=null;
		InputStreamReader sReader=null;
		try
		{
			String str = BaseConstant.FFMPEG_PATH+" "+cmd;
			System.out.println (str);
			Process p = Runtime.getRuntime ().exec (str);//启动两个线程,一个线程负责读标准输出流,另一个负责读标准错误流
			//获取进程的标准输入流
			final InputStream is1 = p.getInputStream();
			//获取进城的错误流
			final InputStream is2 = p.getErrorStream();
			new Thread() {
				public void run() {
					BufferedReader br1 = new BufferedReader(new InputStreamReader(is1));
					try {
						String line1 = null;
						while ((line1 = br1.readLine()) != null) {
							if (line1 != null){}
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
					finally{
						try {
							is1.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			}.start();

			new Thread() {
				public void  run() {
					BufferedReader br2 = new  BufferedReader(new  InputStreamReader(is2));
					try {
						String line2 = null ;
						while ((line2 = br2.readLine()) !=  null ) {
							if (line2 != null){}
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
					finally{
						try {
							is2.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			}.start();
			try
			{
				p.waitFor ();
				p.destroy();
			}
			catch (InterruptedException e)
			{
				e.printStackTrace ();
			}
			return null;
		}
		catch (IOException e)
		{
			e.printStackTrace ();
		}
		return null;
	}
}

更多ffmepg指令

FFmpegCmd.java:

public class FFmpegCmd {
	/**
	 * 扩大分辨率
	 * -y 覆盖输入
	 * -i 视频文件地址
	 */
	private static final String EXPAND_BOUNDARY="  -y -i  %s -vf  scale=%s:%s %s";
	private static final Integer AUTO=-2;

	/**
	 * 设置封面
	 *
	 * -i %s -map 1 -map 0 -c copy -disposition:v:1 attached_pic -y %s
	 *
	 *  ffmpeg  -i 第一集-妖雾重回-1.mp4 -i E:\video\huluwa\cover3.jpg -map 0 -map 1 -c copy -c:v:1 png  -disposition:v:1 attached_pic E:\video\huluwa\success
	 */
	private static final String SETTING_COVER="  -i %s -i %s -map 0 -map 1 -c copy -c:v:1 png  -disposition:v:1 attached_pic %s";
	private static final String VIDEO_INFO="  -i %s ";
	/**
	 * 封面  font 输入路径
	 */
	private static final String Image_OverLay=" -y  -i %s -i %s    -filter_complex overlay=%s:%s    %s";
	/**
	 * 图片截取
	 *  文件源 宽:高:start:end 输出路径
	 */
	private static final String Image_SPLIT=" -y  -i %s     -vf crop=%s:%s:%s:%s    %s";
	/**
	 * 视频分段
	 *  开始时间00:00:00  视频路径 截取时长 输出路径
	 */
	private static final String Video_SPLIT="-y -ss %s -i %s    -to %s        %s";
	/**
	 * 视频转换
	 */
	private static final String Video_COVERT=" -i %s -c:v copy -c:a copy %s";

	/**
	 * image to video
	 */
	private static final String Image_TO_VIdeo=" -f image2 -r 1 -i %s  -vcodec h264  %s";


	private static final String Video_TS=" -i %s -c copy -bsf:v h264_mp4toannexb -f mpegts  %s";

	private static final String Concat="  -i \"concat:%s|%s\" -c copy -bsf:a aac_adtstoasc -movflags +faststart %s";

	/**
	 * 修改分辨率
	 * @param videoPath 文件路径
	 * @param outPath 输出路径
	 * @param width 修改宽度
	 * @param height 修改高度
	 */
	public static void expandBoundaryMethod(String videoPath,String outPath,Integer width,Integer height){
		width = width==null?AUTO:width;
		height = height==null?AUTO:height;
		String cmd = String.format (EXPAND_BOUNDARY,videoPath,width,height,outPath);
		CmdUtil.execCmd (cmd);
	}

	/**
	 * 设置封面
	 * @param videoPath 文件路径
	 * @param imgPath 图片路径
	 * @param outPath 输出路径
	 */
	public static void settingCoverMethod(String videoPath,String imgPath,String outPath){
		String cmd = String.format (SETTING_COVER,videoPath,imgPath,outPath);
		String s = CmdUtil.execCmd (cmd);
		System.out.println (s);
	}

	public static VideoEntity getVideoInfo(String videoPath){

		String cmd = String.format (VIDEO_INFO,videoPath);
		String s = CmdUtil.execCmd (cmd);
		String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";
		Pattern pattern = Pattern.compile(regexDuration);
		Matcher m = pattern.matcher(s.toString());
		VideoEntity videoEntity = new VideoEntity (videoPath);
		if (m.find()) {
			int time = getTimelen(m.group(1));
			System.out.println("视频时长:" + time + "s , 开始时间:" + m.group(2) + ", 比特率:" + m.group(3) + "kb/s");
			videoEntity.setDuration (time);
		}
		return videoEntity;

	}
	private static int getTimelen(String timelen) {
		int min = 0;
		String strs[] = timelen.split(":");
		if (strs[0].compareTo("0") > 0) {
			// 秒
			min += Integer.valueOf(strs[0]) * 60 * 60;
		}
		if (strs[1].compareTo("0") > 0) {
			min += Integer.valueOf(strs[1]) * 60;
		}
		if (strs[2].compareTo("0") > 0) {
			min += Math.round(Float.valueOf(strs[2]));
		}
		return min;
	}
	public static void imageOverlayMethod(String coverImage,String fontImage,Integer width,Integer height,String output){
		String cmd = String.format (Image_OverLay,coverImage,fontImage,width,height,output);
		CmdUtil.execCmd (cmd);
	}
	public static void ImageSplitMethod(String imagePath,Integer width,Integer height,Integer sw,Integer sh,String output ){
		String cmd = String.format (Image_SPLIT,imagePath,width,height,sw,sh,output);
		CmdUtil.execCmd (cmd);
	}
	public static void VideoSplitMethod(String videoPath,String start,String length,String output ){
		String cmd = String.format (Video_SPLIT,start,videoPath,length,output);
		CmdUtil.execCmd (cmd);
	}

    public static void videoConvert(String path,String outPath) {
		String cmd = String.format(Video_COVERT,path,outPath);
		CmdUtil.execCmd(cmd);
    }

	public static void ImageToVodeoMethod(String path, String outPutPath) {
		String cmd = String.format(Image_TO_VIdeo,path,outPutPath);
		CmdUtil.execCmd(cmd);
	}

	public static void toVideoTs(String path, String s) {
		String cmd = String.format(Video_TS,path,s);
		CmdUtil.execCmd(cmd);
	}

	public static void ConcatMethod(String imgPath, String vPath, String outPut) {
		String cmd = String.format(Concat,imgPath,vPath,outPut);
		CmdUtil.execCmd(cmd);
	}
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【开发经验】通过ffmpeg进行视频剪辑 的相关文章

  • Python3之3天极速入门五迭代器与生成器

    34 34 34 Python3 迭代器与生成器 迭代是Python最强大的功能之一 xff0c 是访问集合元素的一种方式 迭代器是一个可以记住遍历的位置的对象 迭代器对象从集合的第一个元素开始访问 xff0c 直到所有的元素被访问完结束
  • 记一篇在sata固态上安装好系统的电脑上加装m2固态硬盘,是如何重装系统的

    倒腾了块三星的m2接口固态硬盘 xff0c 但是死活装不上系统 问了好多人终于解决了 xff0c 现在总结一下 xff0c 万一有人用得着 m2固态装好之后正常启动 我用的是大白菜制作工具 xff0c 按普通的做系统盘的方式做好一个启动盘
  • 睿客云盘更新日志

    睿客云盘PC版本 V3 0 7 睿客云盘PC版 更新内容 xff1a 1 修复登录客户端提示网络异常问题 2 修复视频文件右键打开播放失败问题 3 修复分享 64 我功能部分异常问题 4 新增支持睿客网账号登录 5 优化视频播放窗口 202
  • HDFS中web端查看/tmp目录与/user目录时权限不足的问题解决

    在查看browse directory时 xff0c 点击 tmp 或 user xff0c 无法进入 xff0c 报错 xff1a Permission denied user 61 dr who access 61 READ EXECU
  • 【WSL】WSL迁移教程

    写在前面 如果我们是通过Windows Store进行安装的 xff0c 就会默认安装到C盘 在使用过程中 xff0c WSL占用空间会越来越大 xff0c 很容易让C盘爆满 xff0c 所以我们需要将其迁移到其他非C盘的地方 终止正在运行
  • 【WSA】Win11 安卓子系统配置上网方法

    搜索系统环境变量 xff1a 在里面添加ADB的安装路径 xff1a 在终端里输入adb version xff0c 测试adb是否正常工作 xff1a 在终端里输入ipconfig xff0c 查看安卓子系统IP地址 xff1a 在终端输
  • 【WSA】Win11安卓子系统提示VirtWifi的连接受限的解决方法

    问题描述 每次WSA启动时都会有如下提示 xff1a 虽说不影响使用 xff0c 但是看着实在是闹心 解决方案 1 下载ADB工具 xff1a Platform tools下载 Platform tools 安卓调试工具包 官方版下载 系统
  • Centos CA自签证书服务器及自签证书配置手册

    Centos CA自签证书服务器及自签证书配置手册 1 准备工作1 1 系统版本信息1 2 创建必要的目录和文件 2 创建CA2 1 生成CA私钥文件 Key 2 2 生成CA自签名证书2 3 生成自签名证书 拓展部分 2 4 etc pk
  • AttributeError: ‘DataFrame‘ object has no attribute ‘ix‘

    问题原因 pandas版本0 20 0及其以后版本中 xff0c ix已经不被推荐使用 问题解决 使用loc和iloc替换 loc loc gets rows or columns with particular labels from t
  • 使用OLS摘要解释线性回归的结果

    下面是一个回归过程 xff0c 用于拟合收入和教育情况 span class token function import span pandas as pd span class token function import span mat
  • 夏皮罗-威尔克检验(Shapiro–Wilk test)

    1介绍 夏皮罗 威尔克检验是一种在频率上统计检验中检验正态性的方法 它在1965年由夏皮罗和威尔克发表 2 理论 Shapiro Wilk检验检验了样本x 1 xff0c xff0c x n来自正态分布总体的原假设 该检验统计量是 3 解解
  • KS检验

    1 KS 检验 xff08 Kolmogorov Smirnov test xff09 Kolmogorov Smirnov是比较一个频率分布f x 与理论分布g x 或者两个观测值分布的检验方法 其原假设H0 两个数据分布一致或者数据符合
  • git status 命令详解

    git status命令表示 xff1a 文件 xff0c 文件夹在工作区 xff0c 暂存区的状态 xff0c 下图就是文件 xff0c 文件夹三种状态 xff1a Changes to be committed use git rest
  • PyTorch 中的乘法:mul()、multiply()、matmul()、mm()、mv()、dot()

    torch mul 函数功能 xff1a 逐个对 input 和 other 中对应的元素相乘 本操作支持广播 xff0c 因此 input 和 other 均可以是张量或者数字 span class token keyword impor
  • Adblock Plus Rules 自用 2021

    Adblock Plus Rules obsolete ZhihuCSDNBilibiliBaidu 64 64 static zhihu com heifetz lib js 64 64 static zhihu com heifetz
  • pandas函数 apply、iterrows、iteritems、groupyby

    apply DataFrame span class token punctuation span span class token builtin apply span span class token punctuation span
  • PyTorch中 tensor.detach() 和 tensor.data 的区别

    以 a data a detach 为例 xff1a 两种方法均会返回和a相同的tensor xff0c 且与原tensor a 共享数据 xff0c 一方改变 xff0c 则另一方也改变 所起的作用均是将变量tensor从原有的计算图中分
  • 解决Typora的测试版已过期问题 This beta version of Typora is expired, please download and install a newer versio

    错误提示 xff1a The beta version of typora span class token keyword is span expired span class token punctuation span please
  • WSL2 配置SSH 设置开机自启

    WSL2 配置SSH 设置开机自启 WSL2 配置SSH 设置开机自启先说结论完整wsl help WSL2 配置SSH 设置开机自启 尝试了很多博客上的方法没有找到理想的解决方案 xff0c 看了wsl help之后才知道这些方法确实十分
  • Undo Log学习

    一 Undo Log的作用 数据库故障恢复机制的前世今生中提到过 xff0c Undo Log用来记录每次修改之前的历史值 xff0c 配合Redo Log用于故障恢复 这也就是InnoDB中Undo Log的第一个作用 xff1a 1 事

随机推荐

  • 慢SQL解决方案

    一 全表扫描 1 案例 span class token keyword SELECT span span class token function count span span class token punctuation span
  • JAVA17新特性

    2022 年 7 月底 xff0c 甲骨文正式停止对Java SE 7的扩展支持 xff0c 一个有着近 11 年历史的 Java 标准版本迎来生命周期结束 目前最新版本的 Java18 于今年 3 月正式发布 xff0c 并将于 2022
  • 测试——单元测试,集成测试,系统测试,白盒,黑盒

    一 单元测试 1 何为单元测试 单元测试 xff08 unit testing xff09 xff0c 是指对软件中的最小可测试单元进行检查和验证 单元测试通常和白盒测试联系到一起 xff0c 如果单从概念上来讲两者是有区别的 xff0c
  • java对多媒体处理工具

    简介 JAVE Java Audio Video Encoder 类库是一个 ffmpeg 项目的 Java 语言封装 开发人员可以使用 JAVE 在不同的格式间转换视频和音频 例如将 AVI 转成 MPEG 动画 xff0c 等等 ffm
  • 线程池不允许使用Executors创建原因

    1 FixedThreadPool 和 SingleThreadPool 允许的请求队列长度为 Integer MAX VALUE xff0c 可能会堆积大量的请求 xff0c 从而导致 OOM span class token keywo
  • 高分子结晶的新进展、新模型

    高分子结晶的新进展 新模型 高分子的结晶结构与形态对高分子材料的物理机械性能具有重要影响 xff0c 高分子结晶过程的分子机理 结晶热力学 结晶动力学等构成了高分子物理的重要内容 高分子结晶的研究经历了从溶液培养单晶 xff0c 确定折迭链
  • wsl安装图形界面——体验有脸有面的图形界面

    不得不说 xff0c 自动windows支持linux子系统之后 xff0c 这又使其成为一大卖点 首先 Linux 的分发版本非常多 xff0c 例如有 xff1a Ubuntu openSUSE SUSE Linux Fedora Ka
  • E: 有未能满足的依赖关系。请尝试不指明软件包的名字来运行“apt --fix-broken install”(也可以指定一个解决办法)。

    国产银河麒麟系统下在使用apt install xxxxxxx 出现如下错误 正在读取软件包列表 完成 正在分析软件包的依赖关系树 正在读取状态信息 完成 您也许需要运行 apt fix broken install 来修正上面的错误 下列
  • 【CCF CSP-20160903】炉石传说

    CCF CSP 20160903 炉石传说 C 43 43 代码 span class token macro property span class token directive hash span span class token d
  • 树莓派介绍

    文章目录 一 树莓派介绍二 树莓派分类 一 树莓派介绍 树莓派 xff0c xff08 英语 xff1a Raspberry Pi xff0c 简写为RPi xff0c 别名为RasPi RPI xff09 是为学习计算机编程教育而设计 x
  • Docker核心技术-联合文件系统

    联合文件系统 xff08 UnionFS xff09 是一种分层 轻量级并且高性能的文件系统 xff0c 它支持对文件系统的修改作为一次提交来一层层的叠加 xff0c 同时可以将不同目录挂载到同一个虚拟文件系统下 联合文件系统是 Docke
  • Spark SQL与Hive SQL解析执行流程

    转载专用 xff1a 读到了好文章 xff0c 用于分享收藏 xff0c 侵权删 转发自大佬 xff1a 数据人生coding xff0c https yuanmore blog csdn net type 61 blog 转发自大佬 xf
  • 银河麒麟V10服务器系统安装教程及注意事项

    系统安装 1 引导安装 从U盘引导安装时首先进入的是安装引导页面 xff0c 如下图 xff1a 使用向上方向键 lt gt 选择 Install Kylin Linux Advanced Server V10 xff0c 按进入安装过程
  • 1012 - iOS之View Controllers的理解

    需求现在只是把navigationController的导航栏字体给去掉 xff0c 不过既然都看了 xff0c 那就直接刚一下吧 阅读官网文档的顺序 xff1a Managing Content in Your App 39 s Wind
  • CentOS7 linux下yum安装redis以及使用 及 外网访问

    一 安装redis 1 检查是否有redis yum 源 1 yum install redis 2 下载fedora的epel仓库 1 yum install epel release 3 安装redis数据库 1 yum install
  • MySQL8.0忘记密码后重置密码(亲测有效)

    实测 xff0c 在mysql8系统下 xff0c 用mysqld console skip grant tables shared memory可以无密码启动服务 服务启动后 xff0c 以空密码登入系统 mysql exe u root
  • My uBlock static filters

    My uBlock static filters 2022 百度 2022 06 https pan baidu com pan baidu com bpapi analytics pan baidu com rest 2 0 pcs ad
  • conda安装包报错:The current user does not have write permissions to the target environment(当前用户没有写入权限)

    问题 xff1a 在Winodws 10下使用conda安装第三方包时报错 xff1a EnvironmentNotWritableError The current user does not have write permissions
  • CCF 201809-3元素选择器

    分析 xff1a 这题超级坑 xff0c 当时考试时只得了50分 xff0c 现在重新做一直卡在80分 xff0c 各种复杂情况都考虑到了 xff0c 还是不能ac xff0c 于是尝试三种不同办法解决 xff0c 也均不能AC xff0c
  • 【开发经验】通过ffmpeg进行视频剪辑

    文章目录 前言一 视频剪辑1 1 生成标题2 文字和背景图叠加3 视频切割4 视频和背景图叠加结果演示java执行cmd指令更多ffmepg指令 前言 突然发现抖音有有一些人发布电视剧的精彩片段 xff0c 并且还获得了很多的点赞 突然发现