需要通过Java给视频添加时间戳水印(以某个传入时间为起始),通过ffmpeg应该怎么做?命令行怎么写?

  1. 需求是通过Java来给上传的视频加上以某时间点为开始的时间水印,
  2. 入参为开始的时间点是 yyyy-mm-dd HH:MM:SS格式或时间戳。
  3. 水印随视频的播放实时增加,即动态水印。
阅读 6.2k
2 个回答
  1. 命令行

    
    ffmpeg -i src.mp4  -vf "drawtext='fontfile=FreeSans.ttf:fontsize=35:x=100:y=100:text=%{pts\: localtime\:1629338400}'" output.mp4 -y
  2. 解释命令行
    -vf:视频过滤器
    -y:覆盖同名文件
    src.mp4:编辑的视频路径
    drawtext:绘制文本内容,以及样式设置(x,y指定水印位置,fontsize指定大小)
    output.mp4:完成后的视频路径
    localtime\:1629338400:数字为时间戳
  3. Java获取特定时间的时间戳

    //获取到2021-8-19 10:00:00的时间戳 秒
    LocalDate date = LocalDate.of(2021,8,19);
    LocalTime time = LocalTime.of(10,0,0);
    //设置偏移量,用北京时间计算
    long ll = LocalDateTime.of(date,time).toInstant(ZoneOffset.of("+8")).getEpochSecond();
    System.out.println(ll);
  4. Java执行命令行
    通过Java的Process类

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.io.IOException;
    import java.util.concurrent.LinkedBlockingDeque;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    /**
     * 节选部分测试代码
     * @data 2021/8/26
     */
    public class ProcessExecute {
    
     private static final Logger log = LoggerFactory.getLogger(ProcessExecute.class);
    
     static ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(5,
             10,
             3,
             TimeUnit.SECONDS,
             new LinkedBlockingDeque<>(1000),
             new VideoThreadFactory("linux-微服务"),
             new ThreadPoolExecutor.AbortPolicy());
    
     public String addWatermark(String filePath, String fileName, String timestamp){
         String srcFile = filePath+fileName;
         String waterFile = filePath+"2-"+fileName;
         String fontfile = "/home/spmq/font/HarmonyOS_Sans_Medium.ttf";
         String cmd = "ffmpeg -i "+srcFile+" -vf \"drawtext='fontfile="+fontfile+":fontsize=35:text=%{pts\\: localtime\\:"+timestamp+"}'\" "+waterFile+" -y";
         log.info("命令行:{}",cmd);
         //linux上需要加上这行
         String[] linuxCmd = {"sh","-c",cmd};
         try {
             Process process = Runtime.getRuntime().exec(linuxCmd);
             Thread t1 = new CleanInputCache(process.getInputStream(),"INFO");
             Thread t2 = new CleanInputCache(process.getErrorStream(),"CMD-E");
             poolExecutor.execute(t1);
             poolExecutor.execute(t2);
             process.waitFor();
             log.info("任务执行完毕!");
         } catch (IOException e) {
             log.error(e.getMessage());
         } catch (InterruptedException e) {
             log.error(e.getMessage());
         }
         return waterFile;
     }
    }
  5. ffmpeg部署至Linux
    ffmpeg官网提供的Linux下载地址https://johnvansickle.com/ffm...
    选择版本下载,内核较老的需要选择旧版本。
    安装过程:
    (1)将下载的文件上传到linux上
    (2)解压

    xz -d ffmpeg-git-amd64-static.tar.xz
    
    tar -xvf ffmpeg-git-amd64-static.tar

    (3)进入解压出的文件夹

    cd ffmpeg-git-20190424-amd64-static/

    (4)测试

    ./ffmpeg

    (5)想要ffmpeg命令全局可用,可以在bin目录加个链接

    cd /usr/bin
    
    ln -s /data/software/ffmpeg-git-20190424-amd64-static/ffmpeg ffmpeg
    
    ln -s /data/software/ffmpeg-git-20190424-amd64-static/ffprobe ffprobe
  6. 补充
    windows下载地址:https://www.gyan.dev/ffmpeg/b...
    多线程加水印命令行:

    ./ffmpeg -i source.mp4 -vf "[in]drawtext=x=w-tw-20:y=20:text='%{pts\:localtime\:1629443615}':fontsize=20:fontcolor=red[text];movie='/opt/test/videoTool/icon.png'[wm];[text][wm]overlay=20:20,scale=1920:1080[out]" -threads 2 -preset ultrafast -y target.mp4

    中文显示白框问题:搜索答案说与fontfile文件有关(未测试成功),Linux上显示中文正常。
    https://www.freesion.com/arti...
    https://blog.csdn.net/u014552...

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题