其實,在JavaCV中除了FFmpegFrameGrabber和FFmpegFrameRecorder之外,還有一個重要的類,那就是FFmpegFrameFilter。
FFmpegFrameFilter封裝了ffmpeg濾鏡相關操作,使得使用JavaCV進行濾鏡操作變成簡單,關於ffmpeg濾鏡的使用文件可以檢視ffmpeg的文件:http://www.ffmpeg.org/ffmpeg-filters.html。
簡單來說,如果熟悉ffmpeg的濾鏡功能,那麼使用FFmpegFrameFilter的難度不大,下面通過幾個例項演示一下FFmpegFrameFilter的使用方式:
視訊縮放
視訊縮放使用的濾鏡為scale
,語法為:scale=width:height[:interl={1|-1}]
,這裡需要注意的是,JavaCV對視訊輸入的濾鏡命名是固定的:
- 如果是一路視訊,那麼輸入為
in
,輸出為out
- 如果是多路視訊,那麼輸入為
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都可以使用pad
和overlay
組合來實現,下面是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"));
濾鏡效果:
文章原始碼後續整理後將會在公眾號釋出!
=========================================================
關注公眾號,閱讀更多文章。