我是靠谱客的博主 生动裙子,最近开发中收集的这篇文章主要介绍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’

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

在这里插入图片描述

在这里插入图片描述

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所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部