使用xuggle_5.4 实现视频加水印

使用xuggle_5.4 实现视频加水印

实现思路

1.读取视频流
2.对视频的图片做转换【注:视频分图片和音频,两个是不同的处理器】
3.把音频流重新导回
4.输出处理后的视频

引入依赖包

<dependency>
            <groupId>xuggle</groupId>
            <artifactId>xuggle-xuggler</artifactId>
            <version>5.4</version>
            <scope>system</scope>
            <!-- https://mvnrepository.com/artifact/xuggle/xuggle-xuggler/5.4 在这下载-->
            <systemPath>${
   basedir}/lib/xuggle-xuggler-5.4.jar</systemPath>
        </dependency>

实现代码

public static void main(String[] args) {
   
        String inputPath="D:\\Download\\b.mp4";
        String outputPath="D:\\Download\\b231231.mp4";
        StopWatch sw1=new StopWatch();
        sw1.start();
        markToVideo(inputPath,outputPath,"加了个水印");
        sw1.stop();
        System.out.println("mark 未压缩的视频 耗时" + sw1.getTotalTimeSeconds() + "秒");
    }

    private static final Font FONT = new Font("simkai", Font.BOLD, 60);
    private static final AlphaComposite COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
    /**
     * X轴水印之间的间隔
     */
    private static final int X_MOVE = 300;
    /**
     * Y轴水印之间的间隔
     */
    private static final int Y_MOVE = 140;
    // 定义一个名为markToVideo的公共静态方法,该方法接受三个字符串参数:输入路径、输出路径和内容
    public static void markToVideo(String inputPath, String outputPath, String content) {
   
        // 创建一个媒体读取器对象,从输入路径读取视频文件
        IMediaReader reader = ToolFactory.makeReader(inputPath);
        try {
   
            // 设置要生成的缓冲图像类型为3BYTE_BGR,即蓝色、绿色、红色三个通道的BGR格式
            reader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);
            // 不添加动态流
            reader.setAddDynamicStreams(false);
            // 查询元数据
            reader.setQueryMetaData(true);
            // 创建一个媒体写入器对象,将处理后的视频写入到输出路径
            IMediaWriter writer = ToolFactory.makeWriter(outputPath, reader);
            // 为读取器添加一个监听器,监听视频图片事件
            reader.addListener(new MediaToolAdapter() {
   
                @Override
                public void onVideoPicture(IVideoPictureEvent event) {
   
                    // 获取视频图片事件中的图片对象
                    IVideoPicture picture = event.getPicture();
                    // 获取Java数据中的缓冲图像
                    BufferedImage bufferedImage = event.getJavaData();
                    // 创建一个图形2D对象,用于在缓冲图像上绘制文本
                    Graphics2D graphics = bufferedImage.createGraphics();
                    // 打印缓冲图像的宽度和高度
                    System.out.println(bufferedImage.getWidth() + " and " + bufferedImage.getHeight());
                    // 在缓冲图像上创建文本(此处的createText方法未在代码中定义)
                    createText(content, bufferedImage, bufferedImage.getWidth(), bufferedImage.getHeight(), graphics);
                    // 创建一个转换器对象,将缓冲图像从Java的图像格式转换为YUV420P格式
                    IConverter converter = ConverterFactory.createConverter(bufferedImage, IPixelFormat.Type.YUV420P);
                    // 使用转换器将缓冲图像转换为YUV420P格式的视频图片对象
                    IVideoPicture iVideoPicture = converter.toPicture(bufferedImage, picture.getTimeStamp());
                    // 向写入器添加一个音频流,这里并未实际使用音频流,因此参数都是0和默认值
                    writer.addAudioStream(0, 0, ICodec.ID.CODEC_ID_H264, bufferedImage.getWidth(), bufferedImage.getHeight());
                    // 将处理后的视频图片对象编码并写入到输出视频文件
                    writer.encodeVideo(0, iVideoPicture);
                }
            });
            // 等待读取器读取完所有数据包(此处为阻塞操作,直到所有数据包处理完毕)
            while (reader.readPacket() == null);
        } catch (Exception e) {
   
            // 捕获并打印异常信息
            e.printStackTrace();
        } finally {
   
            // 关闭读取器对象
            reader.close();
        }
    }

    private static void createText(String content, BufferedImage bufImg, int imgWidth, int imgHeight, Graphics2D graphics) {
   
        //标记的颜色
        Color markColor = new Color(180, 180, 180);
        // 设置水印颜色
        graphics.setColor(markColor);
        // 设置水印透明度 可自定义
        graphics.setComposite(COMPOSITE);
        // 设置倾斜角度
        graphics.rotate(Math.toRadians(-35), (double) bufImg.getWidth() / 2,
                (double) bufImg.getHeight() / 2);
        // 设置水印字体
        graphics.setFont(FONT);
        // 消除java.awt.Font字体的锯齿
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        int xCoordinate = -imgWidth / 2;
        int yCoordinate;
        // 字体长度
        int markWidth = FONT.getSize() * getTextLength(content);
        // 字体高度
        int markHeight = FONT.getSize();
        // 循环添加水印
        double d = 1.5;
        while (xCoordinate < imgWidth * d) {
   
            yCoordinate = -imgHeight / 2;
            while (yCoordinate < imgHeight * d) {
   
                graphics.drawString(content, xCoordinate, yCoordinate);
                yCoordinate += markHeight + Y_MOVE;
            }
            xCoordinate += markWidth + X_MOVE;
        }
        // 释放画图工具
        graphics.dispose();
    }

    /**
     * 计算水印文本长度
     * 1、中文长度即文本长度 2、英文长度为文本长度二分之一
     *
     * @param text 文字
     * @return int
     */
    public static int getTextLength(String text) {
   
        // 水印文字长度
        int length = text.length();
        for (int i = 0; i < text.length(); i++) {
   
            String s = String.valueOf(text.charAt(i));
            if (s.getBytes().length > 1) {
   
                length++;
            }
        }
        length = length % 2 == 0 ? length / 2 : length / 2 + 1;
        return length;
    }

相关推荐

  1. 使用xuggle_5.4 实现视频

    2023-12-23 14:50:02       39 阅读
  2. js实现给html

    2023-12-23 14:50:02       37 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-23 14:50:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-23 14:50:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-23 14:50:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-23 14:50:02       18 阅读

热门阅读

  1. mockito-study-api

    2023-12-23 14:50:02       37 阅读
  2. Mac[M1]安装mongodb

    2023-12-23 14:50:02       34 阅读
  3. 掌握 Rust 中的建造者模式

    2023-12-23 14:50:02       47 阅读
  4. Harmonyos系统使用http访问网络和应用数据管理

    2023-12-23 14:50:02       31 阅读
  5. 数据处理演进:EtLT崛起,ELT正在告别历史舞台

    2023-12-23 14:50:02       34 阅读
  6. Golang leetcode59 螺旋矩阵

    2023-12-23 14:50:02       35 阅读
  7. 基于汉宁窗FIR滤波器实现语音信号加噪去噪

    2023-12-23 14:50:02       41 阅读
  8. MySQL数据库

    2023-12-23 14:50:02       32 阅读
  9. 理解计算机中的中断与中断处理

    2023-12-23 14:50:02       46 阅读
  10. log4j rename方法

    2023-12-23 14:50:02       36 阅读
  11. python使用selenium无法获取frame完整内容的问题

    2023-12-23 14:50:02       45 阅读
  12. 基于模板匹配的花朵分类 - MATLAB代码实现

    2023-12-23 14:50:02       36 阅读