javacv-音视频和图像处理

前言

javacv对ffmpeg、opencv等c/c++库(具体哪些库参考源码地址)进行了封装,提供了友好的基于java的访问接口。下面来看下这些接口:

Frame 数据帧

对音频帧、视频帧和数据帧的抽象,有三种类型的数据帧:

public static enum Type {
    VIDEO,
    AUDIO,
    DATA
}

Frame是音视频数据的容器,可以通过FrameConverter<F>转换到其他平台的数据结构类。

FrameConverter 帧转换器

帧数据转换器,用于各种平台数据类之间的转换。它的实现有:
在这里插入图片描述
可以转成Android的Bitmap、Java的BufferedImage、JavaFX的Image、OpenCV的IplImage&Mat&org.opencv.core.Mat等。可以看出这个库可用于Android和Java两个平台。

FrameGrabber 帧抓取器

帧抓取器从从音视频源中抓取帧(视频帧,音频帧,数据帧等)数据,是数据提取过程。它的实现根据平台的不同也是多种多样,版本1.5.3如下:
在这里插入图片描述
根据具体场景(设备,文件,流等)的不同,可以选择最合适的帧抓取器。

常用的模版代码是一个循环不断拉取帧,然后进行处理,下面展示用ffmpeg帧抓取器获取视频文件的代码如下:

public static <T> List<T> videoFrameMap(String videoFile, BiFunction<Integer, Frame, T> f) {
        return Try.ofCallable(new Callable<List<T>>() {
            @Override
            public List<T> call() throws Exception {
                FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(new File(videoFile));
                grabber.start();
                int frameCount = grabber.getLengthInVideoFrames();
                List<T> res = new ArrayList<>();
                int i = 0;
                while (i < frameCount) {
                    Frame frame = grabber.grabImage();
                    if (frame != null) {
                        res.add(f.apply(i, frame.clone()));
                    }
                    ++i;
                }
                grabber.stop();
                return res;
            }
        }).get();
    }

FrameRecorder 帧记录器

帧记录器把帧数据记录到文件和流中。版本1.5.3的实现有两个:
在这里插入图片描述
下面演示从一个视频文件中读取视频流,然后进行灰度处理,最后推到rtmp服务器上:

public static void videoFrameRedirect(String src, String dst, Function<Frame, Frame> f) {
        Try.ofCallable(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(src);//使用ffmpeg抓取器
                grabber.start();//开启抓取器

                int width = grabber.getImageWidth();
                int height = grabber.getImageHeight();

                FrameRecorder recorder = FrameRecorder.createDefault(dst, width, height);
                //设置视频编码和格式
                recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264,编码
                recorder.setFormat("flv");//封装格式,如果是推送到rtmp就必须是flv封装格式
                recorder.setFrameRate(grabber.getFrameRate());

                recorder.start();//开启记录器

                while (true) {
                    Frame frame = grabber.grabImage();
                    if (frame == null) {
                        break;
                    }
                    System.err.println(frame.timestamp);
                    recorder.setTimestamp(frame.timestamp);
                    //进行图片处理
                    if (f != null) {
                        frame = f.apply(frame);
                    }
                    recorder.record(frame);
                }

                recorder.stop();
                recorder.release();
                grabber.stop();
                grabber.release();
                return null;
            }
        }).get();
    }

使用groovy测试:

import org.bytedeco.javacv.Frame
import org.bytedeco.javacv.Java2DFrameUtils
import org.bytedeco.opencv.opencv_core.Mat

import static org.bytedeco.opencv.global.opencv_imgproc.COLOR_BGR2GRAY
import static org.bytedeco.opencv.global.opencv_imgproc.cvtColor

void testVideoRedirect() {
        VideoFrameRedirect.videoFrameRedirect("D:\\pet.mp4", "rtmp://localhost:1935/live/abc", new Function<Frame, Frame>() {
            @Override
            Frame apply(Frame frame) {
                Mat dst = new Mat()
                cvtColor(Java2DFrameUtils.toMat(frame), dst, COLOR_BGR2GRAY)
                return Java2DFrameUtils.toFrame(dst)
            }
        })
    }

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

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaCV 是一个基于 OpenCV 和 FFmpeg 的 Java 库,主要用于图像和视频处理。虽然它本身不提供音频处理的功能,但是可以结合 FFmpeg 的音频处理能力来实现音频合成。 具体来说,可以使用 FFmpeg 的 libavcodec 库来编码音频数据,然后将编码后的数据写入到音频文件中。以下是一个简单的示例代码,演示如何使用 JavaCV 和 FFmpeg 合成音频: ```java import org.bytedeco.javacv.*; import org.bytedeco.ffmpeg.avcodec.*; public class AudioSynthesis { public static void main(String[] args) throws Exception { // 音频参数设置 int sampleRate = 44100; int channels = 2; int bitRate = 128000; int durationInSeconds = 10; // 创建音频编码器 AVCodec codec = avcodec_find_encoder(AVCodecID.AV_CODEC_ID_MP3); AVCodecContext codecContext = avcodec_alloc_context3(codec); codecContext.sample_fmt(AVSampleFormat.AV_SAMPLE_FMT_S16); codecContext.sample_rate(sampleRate); codecContext.channels(channels); codecContext.bit_rate(bitRate); avcodec_open2(codecContext, codec, null); // 创建音频输出文件 FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("output.mp3", channels); recorder.setAudioCodec(codecContext.codec_id()); recorder.setAudioChannels(channels); recorder.setAudioBitrate(bitRate); recorder.setSampleRate(sampleRate); recorder.start(); // 生成音频数据并写入文件 for (int i = 0; i < durationInSeconds * sampleRate; i++) { short[] samples = new short[channels]; // 此处生成音频数据的代码可以自行替换 samples[0] = (short) (Math.sin(2 * Math.PI * 440 * i / sampleRate) * Short.MAX_VALUE); samples[1] = (short) (Math.sin(2 * Math.PI * 880 * i / sampleRate) * Short.MAX_VALUE); avcodec_send_frame(codecContext, av_frame_alloc()); AVPacket packet = av_packet_alloc(); avcodec_receive_packet(codecContext, packet); recorder.recordPacket(packet); } // 关闭编码器和输出文件 avcodec_close(codecContext); recorder.stop(); recorder.release(); } } ``` 在这个示例代码中,我们选择了 MP3 编码器来编码音频数据,并将编码后的数据写入到名为 output.mp3 的音频文件中。生成音频数据的代码部分可以根据实际需求自行替换。在实际使用中,还需要考虑音频格式、编码器参数等方面的设置,以达到最佳的音频合成效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值