我是靠谱客的博主 生动裙子,这篇文章主要介绍ffmpeg和JavaCV一、视频相关的基础知识二、ffplay三、ffmpeg,现在分享给大家,希望可以做个参考。

在这里插入图片描述

一、视频相关的基础知识

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’

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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(); } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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()); } } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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(); } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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一、视频相关内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(104)

评论列表共有 0 条评论

立即
投稿
返回
顶部