无论是歌曲,小说,还是技术文章从古至今都是各种抄袭,各种拿来就用,随着技术的发展,朋友圈的图片,商铺的图片,也开始各种拿来就用,所以发明了水印,当然不止图片有水印,视频也可以有的。
这期我们介绍的是添加静态文字水印,当然可以添加图片水印,动态文字水印,只是这期的重点是添加静态文字水印。添加静态文字水印有两种方法。
不论怎么样,都要引入 Maven
<!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.2</version>
</dependency>
第一种(使用 FFmpeg 原生的)
FFmpegFrameFilter (过滤器)
FFmpegFrameFilter 功能很强大,这个类一共有三个构造方法。
第一个
//过滤音频,给音频做一些处理
public FFmpegFrameFilter(String afilters, int audioChannels)
第二个
//过滤视频,给视频做一些处理
public FFmpegFrameFilter(String filters, int imageWidth, int imageHeight)
第三个
//同时过滤音频与视频,给音视频做一些处理
public FFmpegFrameFilter(String videoFilters, String audioFilters, int imageWidth, int imageHeight, int audioChannels)
videoFilters 这个是视频的一些处理设置,具体参考 ffmpeg.audioFilters 这个是音频的一些处理设置,具体参考 ffmpeg.imageWidth imageHeight这个是视频的宽和高。audioChannels 这个是音频的通道。
都说清楚了,那我们上代码吧。
常量代码
//设置修改视频的路径
public static final String VIDEO_OLD_PATH =
"/voicedemo/src/main/java/xin/zhuyao/voicedemo/video/1608599180608-0.mp4";
//设置新生产视频的路径
public static final String VIDEO_NEW_PATH =
"/voicedemo/src/main/java/xin/zhuyao/voicedemo/test/1608599180608-1.mp4";
//字体
private static final String FONT_PATH =
"/Library/Fonts/Arial\\ Unicode.ttf";
核心代码
/**
* 添加字体水印
* @param content 水印内容
* @throws Exception Exception
*/
public static void addTextByFFmpegFrame(String content) throws Exception {
//抓取器
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(VIDEO_OLD_PATH);
//打开抓取器
grabber.start();
//录播器
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(
VIDEO_NEW_PATH,
grabber.getImageWidth(),
grabber.getImageHeight(),
grabber.getAudioChannels());
// 视频相关配置,取原视频配置
recorder.setFrameRate(grabber.getFrameRate());
recorder.setVideoCodec(grabber.getVideoCodec());
recorder.setVideoBitrate(grabber.getVideoBitrate());
// 音频相关配置,取原音频配置
recorder.setSampleRate(grabber.getSampleRate());
recorder.setAudioCodec(grabber.getAudioCodec());
recorder.setAudioBitrate(grabber.getAudioBitrate());
//开启录播器
recorder.start();
//过滤器
String filterContent = "drawtext=fontfile="+ FONT_PATH + ": text='" + content + "': fontsize=h/30: x=(w-text_w)/2: y=(h-text_h*2)";
FFmpegFrameFilter fFmpegFrameFilter = new FFmpegFrameFilter(
filterContent,
grabber.getImageWidth(),
grabber.getImageHeight());
//开启视频过滤器
fFmpegFrameFilter.start();
Frame frame;
while ((frame = grabber.grab()) != null) {
if (frame.image != null) {
fFmpegFrameFilter.push(frame);
recorder.record(fFmpegFrameFilter.pullImage());
}
}
fFmpegFrameFilter.close();
recorder.close();
grabber.close();
}
测试
public static void main(String[] args) throws Exception {
addTextByFFmpegFrame("程序员小朱");
}
第二种(我取每一帧,然后把文字加在每一帧上)
这个逻辑很清楚吧,就是视频里取每一帧图片,然后添加上文字在放上去。
常量代码
//设置修改视频的路径
public static final String VIDEO_OLD_PATH =
"/voicedemo/src/main/java/xin/zhuyao/voicedemo/video/1608599180608-0.mp4";
//设置新生产视频的路径
public static final String VIDEO_NEW_PATH =
"/voicedemo/src/main/java/xin/zhuyao/voicedemo/test/1608599180608-1.mp4";
//字体
private static final String FONT_PATH =
"/Library/Fonts/Arial\\ Unicode.ttf";
核心代码
public static void addTextByGraphics(String context) throws Exception {
// 设置源视频、加字幕后的视频文件路径
FFmpegFrameGrabber grabber =
new FFmpegFrameGrabber(VIDEO_OLD_PATH);
grabber.start();
FFmpegFrameRecorder recorder =
new FFmpegFrameRecorder(VIDEO_NEW_PATH,
grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
// 视频相关配置,取原视频配置
recorder.setFrameRate(grabber.getFrameRate());
recorder.setVideoCodec(grabber.getVideoCodec());
recorder.setVideoBitrate(grabber.getVideoBitrate());
// 音频相关配置,取原音频配置
recorder.setSampleRate(grabber.getSampleRate());
recorder.setAudioCodec(grabber.getAudioCodec());
recorder.setAudioBitrate(grabber.getAudioBitrate());
recorder.start();
Java2DFrameConverter converter = new Java2DFrameConverter();
Frame frame;
while ((frame =grabber.grab()) != null) {
// 从视频帧中获取图片
if (frame.image != null) {
BufferedImage bufferedImage = converter.getBufferedImage(frame);
// 对图片进行文本合入
bufferedImage = addText(bufferedImage, context);
// 视频帧赋值,写入输出流
recorder.record(converter.getFrame(bufferedImage));
}
//配置音乐
if (frame.samples != null) {
recorder.record(frame);
}
}
recorder.close();
grabber.close();
}
/**
* 图片添加文本
*
* @param bufImg bufImg
* @param content content
* @return BufferedImage
*/
private static BufferedImage addText(BufferedImage bufImg, String content) {
Graphics2D graphics = bufImg.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
//设置图片背景
graphics.drawImage(bufImg, 0, 0, bufImg.getWidth(), bufImg.getHeight(), null);
//设置字体
Font font= new Font("宋体", Font.BOLD, 32);
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
graphics.setFont(font);
int textWidth =metrics.stringWidth(content);
graphics.drawString(content, (bufImg.getWidth() - textWidth) / 2, bufImg.getHeight() / 2);
graphics.dispose();
return bufImg;
}
public static void main(String[] args) throws Exception {
addTextByGraphics("程序员小朱");
}