zoukankan      html  css  js  c++  java
  • JavaCV 视频滤镜(LOGO、滚动字幕、画中画、NxN宫格)

    其实,在JavaCV中除了FFmpegFrameGrabber和FFmpegFrameRecorder之外,还有一个重要的类,那就是FFmpegFrameFilter。

    FFmpegFrameFilter封装了ffmpeg滤镜相关操作,使得使用JavaCV进行滤镜操作变成简单,关于ffmpeg滤镜的使用文档可以查看ffmpeg的文档:http://www.ffmpeg.org/ffmpeg-filters.html

    其他关于JavaCV的文章,可以通过下面的链接查看:
    JavaCV-开发系列文章汇总篇(https://www.cnblogs.com/itqn/p/14696221.html)

    简单来说,如果熟悉ffmpeg的滤镜功能,那么使用FFmpegFrameFilter的难度不大,下面通过几个实例演示一下FFmpegFrameFilter的使用方式:

    视频缩放

    视频缩放使用的滤镜为scale,语法为:scale=height[:interl={1|-1}],这里需要注意的是,JavaCV对视频输入的滤镜命名是固定的:

    1. 如果是一路视频,那么输入为in,输出为out
    2. 如果是多路视频,那么输入为n:v,输出为v,这里的n就是第几路视频输入

    了解了这一点之后,使用FFmpegFrameFilter就很简单了,下面以视频缩放为例,完整的代码如下:

    public class Scale {
    
      public static void main(String[] args) throws IOException {
    
        String filterStr = "scale=320:240[out]";
        //
        FFmpegFrameGrabber stream0 = new FFmpegFrameGrabber(new File("F:/Video/1.mp4"));
        stream0.start();
        // width=640, height=352
        System.out.println("width=" + stream0.getImageWidth() + ", height=" + stream0.getImageHeight());
        //
        FFmpegFrameFilter filter = new FFmpegFrameFilter(filterStr, stream0.getImageWidth(), stream0.getImageHeight());
        filter.start();
        //
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(new File("stream0.mp4"), 320, 240);
        recorder.setFormat("mp4");
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.start();
    
        int idx = 0;
        Frame frame0, frame;
        while ((frame0 = stream0.grabImage()) != null) {
          filter.push(frame0);
          frame = filter.pullImage();
          if (frame != null && frame.image != null) {
            recorder.record(frame);
          }
          if (idx++ > 100) {
            break;
          }
        }
        recorder.close();
        filter.close();
        stream0.close();
      }
    }
    

    滤镜效果:

    视频填充

    视频填充效果使用的滤镜为pad,语法为:pad=width[:height[:x[:y[:color]]]], FFmpegFrameFilter使用实例跟视频缩放一样,不过滤镜要调整为下面这句:

    String filterStr = "pad=700:412:30:30:pink[out]";
    

    另外录制宽高改为原视频宽高:

    FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(new File("stream0.mp4"), stream0.getImageWidth(), stream0.getImageHeight());
    

    滤镜效果:

    LOGO、字幕

    为视频添加LOGO和字幕(滚动)的滤镜相对于前面两个要复杂一点,不过Java代码实现是一样的,采用的滤镜如下:

    movie='logo.png'[logo];[in]drawtext=text='我是滚动字幕--HiIT青年':fontfile=simhei.ttf:y=h-line_h-10:x=w-(t-4.5)*w/5.5:fontcolor=white:fontsize=40:shadowx=2:shadowy=2[text];[text][logo]overlay=15:15[out]
    

    滤镜效果:

    视频合成

    前面提到的都是一路视频操作,对于多路视频的滤镜相对于单路视频有点区别,就是输入有in变成n:v,输出由out变成v, 下面是两路视频合成的完整源码:

    public class Hstack {
    
      public static void main(String[] args) throws IOException {
    
        String filterStr = "[0:v][1:v]hstack=inputs=2[v]";
        //
        FFmpegFrameGrabber stream0 = new FFmpegFrameGrabber(new File("F:/Video/1.mp4"));
        FFmpegFrameGrabber stream1 = new FFmpegFrameGrabber(new File("F:/Video/1.mp4"));
        stream0.start();
        stream1.start();
        // width=640, height=352
        System.out.println("width=" + stream0.getImageWidth() + ", height=" + stream0.getImageHeight());
        //
        FFmpegFrameFilter filter = new FFmpegFrameFilter(filterStr, stream0.getImageWidth(), stream0.getImageHeight());
        filter.setVideoInputs(2);
        filter.start();
        //
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(new File("stream0.mp4"), stream0.getImageWidth(), stream0.getImageHeight());
        recorder.setFormat("mp4");
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.start();
    
        int idx = 0;
        Frame frame0, frame1, frame;
        while ((frame0 = stream0.grabImage()) != null && (frame1 = stream1.grabImage()) != null) {
          filter.push(0, frame0);
          filter.push(1, frame1);
          frame = filter.pullImage();
          if (frame != null && frame.image != null) {
            recorder.record(frame);
          }
          if (idx++ > 200) {
            break;
          }
        }
        recorder.close();
        filter.close();
        stream0.close();
        stream1.close();
      }
    }
    

    滤镜效果:

    画中画

    画中画滤镜其实跟两路视频合成差不多,不过用的是overlay,语法为:overlay[=x:y[[:rgb={0, 1}]]。下面一个画中画效果的滤镜例子:

    String filterStr = "[0:v]scale=iw/2:ih/2[a];[1:v][a]overlay=30:30[v]";
    

    滤镜效果:

    NxN N宫格视频

    其实不管是NxN,还是1xN,Nx1都可以使用padoverlay组合来实现,下面是2x2四宫格的滤镜:

    String filterStr = "[0:v]pad=iw*2:ih*2[a];[a][1:v]overlay=w[b];[b][2:v]overlay=0:h[c];[c][3:v]overlay=w:h[v]"; 
    

    四路视频输入:

    FFmpegFrameGrabber stream0 = new FFmpegFrameGrabber(new File("F:/Video/1.mp4"));
    FFmpegFrameGrabber stream1 = new FFmpegFrameGrabber(new File("F:/Video/1.mp4"));
    FFmpegFrameGrabber stream2 = new FFmpegFrameGrabber(new File("F:/Video/1.mp4"));
    FFmpegFrameGrabber stream3 = new FFmpegFrameGrabber(new File("F:/Video/1.mp4"));
    

    滤镜效果:

    文章源码后续整理后将会在公众号发布!

    =========================================================

    HiIT青年
    关注公众号,阅读更多文章。

  • 相关阅读:
    XP和Scrum的比较
    让PowerDesigner支持SQLite 3.0[转]
    对于大型公司项目平台选择j2ee的几层认识(一)
    对于大型公司项目平台选择j2ee的几层认识(三)
    Alpha、Beta、RC、GA版本的区别
    如何在XElement中使用XPath
    对于大型公司项目平台选择j2ee的几层认识(四)
    Thread与BeginInvoke
    对于大型公司项目平台选择j2ee的几层认识(二)
    修复VS 2010的Help Library管理器
  • 原文地址:https://www.cnblogs.com/itqn/p/14686671.html
Copyright © 2011-2022 走看看