为自己的短视频盖一个专属的印章----JavaCV之流媒体水印

简介: 为自己的短视频盖一个专属的印章----JavaCV之流媒体水印

无论是歌曲,小说,还是技术文章从古至今都是各种抄袭,各种拿来就用,随着技术的发展,朋友圈的图片,商铺的图片,也开始各种拿来就用,所以发明了水印,当然不止图片有水印,视频也可以有的。

这期我们介绍的是添加静态文字水印,当然可以添加图片水印,动态文字水印,只是这期的重点是添加静态文字水印。添加静态文字水印有两种方法。

不论怎么样,都要引入 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("程序员小朱");
}
相关文章
|
3月前
黑神话:悟空中的音效设计与音乐制作
【8月更文第26天】在《黑神话:悟空》这款游戏中,音效和背景音乐是构建沉浸式游戏体验的重要组成部分。本文将探讨游戏音效和背景音乐的创作过程,以及它们如何增强游戏氛围。
324 0
|
编解码
荔枝派Zero(全志V3S)开启mplayer,播放音视频
mplayer 是一款开源的多媒体播放器,可以用来播放音视频, mplayer 自带多种格式的解码器,不需要我们再另外安装。本文介绍如何在 荔枝派上移植 mplayer 播放器,基于音频驱动实验。
280 0
|
6月前
|
缓存 安全
Spotify音乐无法播放的问题如何解决
在使用Spotify时,你有没有遇到“该音乐无法播放”的错误?遇到这种错误时,如何进行应对?希望这篇文章能给为你进行解答
|
前端开发 程序员 API
教你实现微信8.0『炸裂』的礼花表情特效
作为一个前端程序员,这就勾起了我的好奇心,虽然我从来没有实现过这样的动画,但是我还是忍不住想要去实现,最终我花了2天时间去看一些库的源码到我自己实现一个类似的效果,在这里我总结一下,并且手把手地教大家怎么学习实现。而🎉有一个自己的名字,叫做五彩纸屑,英文名字叫 confetti。
教你实现微信8.0『炸裂』的礼花表情特效
|
容器
借助开源项目,又好又快的实现视频文件”剧情连拍(剧情截图)”功能
借助开源项目,又好又快的实现视频文件”剧情连拍(剧情截图)”功能
688 0
借助开源项目,又好又快的实现视频文件”剧情连拍(剧情截图)”功能
|
存储 编解码 数据可视化
漏刻有时数据可视化语音留言墙开发日志(微信录音&七牛云amr转换成mp3存储转码)
漏刻有时数据可视化语音留言墙开发日志(微信录音&七牛云amr转换成mp3存储转码)
79 0
防伪彩色二维码的设计制作
彩码指彩色二维码、一般使用QRcode类型,彩码的作用主要是防伪领域
128 0