概述
一、视频相关的基础知识
1、容器
- 固定格式的多媒体文件
- mp4、flv、avi、mkv
2、媒体流
- 时间轴上一段连续的数据
- 一段视频数据、一段声音数据、一段字幕数据
- 压缩的数据需要关联特定的编解码器
3、数据帧
- 一个媒体流由大量的数据帧组成
- 对于压缩数据,帧对应着编解码器的最小处理单元
- 不同媒体流的数据帧交错存储在容器中
- Frame对应压缩前的数据,Packet对应压缩后的数据
4、编解码器
- 以帧为单位实现压缩数据和原始数据之间的相互转换
- 例如图象YUV数据可以通过H264编码器编码为H264帧,H264帧又可以通过H264解码器变为图像数据
- 声音的PCM数据可以通过AAC编码器编码为ACC帧
5、复用
- 将不同的流按照某种规则放入容器
6、解复用
- 将不同的流从某种容器中解析出来
7、帧率
- 视频文件中每一秒的帧数,肉眼想看连续移动的画面至少要15帧/s
8、码率
- 也叫比特率,表示每秒处理的字节数,码率越高视频质量越好,单位是bps
- 知道码率和时长就可以算出文件大小
9、ffmpeg/ffplay/ffprobe
- ffmpeg:超快音视频编码器
- ffplay:媒体播放器
- ffprobe:多媒体流分析器
二、ffplay
- ffplay -ss 00:10:00 -t 10 -x 800 test.mp4 (从10分钟处开始播放test.mp4 10秒,限制画面大小为800*-1)
- ffplay test.mp4 -vf tranpose=1 (旋转视频播放)
三、ffmpeg
查看编码器详细参数 ffmpeg -encoders | findstr 264
音视频参数
-
-vcodec 设定视频编解码器,如果是copy表示拷贝输入视频的编码数据,不作新的处理
-
-vf 视频过滤器
-
-vn 不处理视频,即没有视频
-
-an 不处理音频,即没有音频
-
音频参数就是把v变为a
-
ffmpeg -i in.mp4 -ss 10 -t 10 out.mp4(截取从in.mp4的10-20s内容输出为out.mp4)
-
ffmpeg -i in.mp4 -b:a 192k -ar 48000 -ac 2 -acodec libmp3lame -aframes 200 out.mp3(-b:a 音频码率,-ar采样率, -ac声音的channel数一般为2,-aframes输出音频的帧数)
-
ffmpeg -i in.mp4 -vframes 1000 -b:v 5000k -r 100 -s 1000x700 -aspect 16:9 out.mp4
- -r 100表示每秒100帧,-vframes 1000表示视频一共1000帧,这样视频一共10s
- -b:v 5000k 表示视频码率,即视频每秒的多少比特,越大视频越清晰,生成的视频大小为5000/8/1024*10s=6.14M字节
- -s 表示将视频画面设置的宽高
- -aspect 表示画布的宽高
-
像素格式指定
- -pix_fmt yuv420p
- -pix_fmt rgb24
-
preset crf
-
过滤器 -vf(video filter)
- ffplay -i 100.mp4 -vf crop=iw/2:ih:0:0
- fflpay -i 100.mp4 -vf drawtext=fontsize=60:text=‘hello’
import org.bytedeco.ffmpeg.avformat.AVFormatContext;
import org.bytedeco.ffmpeg.avformat.AVStream;
import org.bytedeco.javacv.*;
import javax.swing.*;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws Exception {
String filename = "C:\Users\程勇\Videos\100.mp4";
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(filename);
grabber.start();
AVFormatContext context = grabber.getFormatContext();
// 视频帧率
int frameRate = (int)grabber.getVideoFrameRate();
// 视频时长
int timeLen = (int)grabber.getLengthInTime() / 1000000;
System.out.println("视频帧率:" + frameRate + ", 视频时长:" + timeLen + "s");
// 视频高度和宽度 1920*1080
int frameWidth = grabber.getImageWidth(), frameHeight = grabber.getImageHeight();
System.out.println("视频宽度:" + frameWidth + ", 视频高度:" + frameHeight);
// 流的数目(一般是两个,视频流+音频流)
for(int i = 0; i < context.nb_streams(); i ++ ){
AVStream stream = context.streams(i);
System.out.println("编码器类型:" + stream.codecpar().codec_type() + ", 编码器id:" + stream.codecpar().codec_id());
}
Frame frame;
// canvas可以显示图象
// CanvasFrame canvas = new CanvasFrame("aaa");
// 记录视频
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("C:\Users\程勇\Videos\200_new.avi", 720, 405, 2);
recorder.setFormat("avi");
recorder.start();
System.out.println(grabber.getLengthInFrames());
int cnt = 0;
while((frame = grabber.grab()) != null){
// canvas.showImage(frame);
recorder.record(frame);
cnt ++ ;
if(cnt % 100 == 0) System.out.println(cnt);
}
System.out.println(cnt);
grabber.close();
recorder.close();
}
}
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
public class VideoConvert {
public static void main(String[] args) throws FFmpegFrameRecorder.Exception, FFmpegFrameGrabber.Exception {
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("C:\Users\程勇\Videos\100.mp4");
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("C:\Users\程勇\Videos\100.flv",
grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
recorder.start(grabber.getFormatContext());
for(;;){
recorder.recordPacket(grabber.grabPacket());
}
}
}
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import java.io.IOException;
public class Cmd {
public static void main(String[] args) throws IOException, InterruptedException {
String ffmpeg = Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);
ProcessBuilder pb = new ProcessBuilder(ffmpeg, "-i", "C:\Users\程勇\Videos\100.mp4",
"-vcodec", "h264", "C:\Users\程勇\Videos\100.avi");
pb.inheritIO().start().waitFor();
}
}
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class VideoGrayProcessor {
final static String videoFolderPath = "C:\Users\程勇\Videos\";
final static String videoName = "100.mp4";
public static void main(String[] args) throws Exception {
videoProcess(videoFolderPath + videoName);
}
//视频水印
public static void videoProcess(String filePath) {
//抓取视频图像资源
FFmpegFrameGrabber videoGrabber = new FFmpegFrameGrabber(filePath);
//抓取视频图像资源
FFmpegFrameGrabber audioGrabber = new FFmpegFrameGrabber(filePath);
try {
videoGrabber.start();
audioGrabber.start();
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(videoFolderPath + "new" + videoName,
videoGrabber.getImageWidth(), videoGrabber.getImageHeight(), videoGrabber.getAudioChannels());
recorder.start();
//处理图像
int videoSize = videoGrabber.getLengthInVideoFrames();
for (int i = 0; i < videoSize; i++) {
Frame videoFrame = videoGrabber.grabImage();
if (videoFrame != null && videoFrame.image != null) {
System.out.println("视频共" + videoSize + "帧,正处理第" + (i + 1) + "帧图片");
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage bi = converter.getBufferedImage(videoFrame);
BufferedImage bufferedImage = grayProcess(bi);
recorder.record(converter.convert(bufferedImage));
}
}
//处理音频
for (int i = 0; i < audioGrabber.getLengthInAudioFrames(); i++) {
Frame audioFrame = audioGrabber.grabSamples();
if (audioFrame != null && audioFrame.samples != null) {
recorder.recordSamples(audioFrame.sampleRate, audioFrame.audioChannels, audioFrame.samples);
}
}
recorder.stop();
recorder.release();
videoGrabber.stop();
audioGrabber.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
//灰度处理
public static BufferedImage grayProcess(BufferedImage bufImg) {
int width = bufImg.getWidth();
int height = bufImg.getHeight();
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
bufImg.setRGB(i, j, grayRGB(bufImg.getRGB(i, j)));
}
}
return bufImg;
}
//rgb灰度转换
private static int grayRGB(int rgb) {
int R = (rgb & 0xff0000) >> 16;
int G = (rgb & 0x00ff00) >> 8;
int B = rgb & 0x0000ff;
//平均值
String average = Integer.toHexString((R + G + B) / 3);
if (average.length() == 1) {
average = "0" + average;
}
//RGB都变成平均值
return Integer.parseInt(average + average + average, 16);
}
}
最后
以上就是生动裙子为你收集整理的ffmpeg和JavaCV一、视频相关的基础知识二、ffplay三、ffmpeg的全部内容,希望文章能够帮你解决ffmpeg和JavaCV一、视频相关的基础知识二、ffplay三、ffmpeg所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复