Java后端音视频

2021-11-07  本文已影响0人  何亮hook_8285

描述

视频文件中包含视频和音频数据,那如何通过Java将处理音视频文件,这里案例使用OpenCV的视觉框架,OpenCV对FFMPEG(音视频)框架做了封装。

OpenCV的jar包支持跨平台:window系统、Linux系统(x86-x64 arm)、macos

核心类

FFmpegFrameGrabber 类方法

方法名称 方法描述
FFmpegFrameGrabber(String filename) 构造函数,实例化传入文件路径,或流媒体地址
setFrameRate 设置视频帧率
setGopSize 设置视频gop,与帧率相同,相当于间隔1秒chan's一个关键帧
setVideoCodec 设置压缩方式 ,如AV_CODEC_ID_H264,AV_CODEC_ID_MJPEG等
setPixelFormat 设置封装格式
setVideoOption 设置ffmpeg参数
start 开启视频解码操作
setOption 设置ffmpeg参数,如:rtsp_transport
grab() 获取一帧解码数据
getImageWidth() 视频宽
getImageHeight() 视频高
getAudioChannels() 音频声道数量,单声道,双声道
grabPacket() FFMPEG包数据

FFmpegFrameRecorder 类方法

方法名称 方法描述
FFmpegFrameRecorder(String filename, int imageWidth, int imageHeight) 设置视频文件存放路径
FFmpegFrameRecorder(String filename, int audioChannels) 设置音频文件存放路径
FFmpegFrameRecorder(String filename, int imageWidth, int imageHeight, int audioChannels) 设置音视频存放路径
setVideoOption 设置视频参数,参考ffmpeg
setFrameRate 设置帧率
setGopSize 设置gop,与帧率相同,相当于间隔1秒chan's一个关键帧
setVideoCodec 设置压缩方式 ,如AV_CODEC_ID_H264,AV_CODEC_ID_MJPEG等
setPixelFormat 设置封装格式
setAudioCodec 设置音频编码格式
start 开始录制
recordPacket 写入AVPacket包数据
grab 写入Frame解压数据

引入Maven依赖

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv-platform</artifactId>
    <version>1.5.6</version>
</dependency>

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>opencv-platform</artifactId>
    <version>4.5.3-1.5.6</version>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>ffmpeg-platform</artifactId>
    <version>4.4-1.5.6</version>
</dependency>

音视频分离存储

package com.xl.ffmpeg;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FFmpegLogCallback;
import org.bytedeco.javacv.Frame;


import static org.bytedeco.ffmpeg.global.avutil.*;

public class Test4 {

    public static void main(String[] args) throws Exception {
        //开启日志
        FFmpegLogCallback.set();

        String inputUrl="2.mp4";

        //抽取视频和音频存储路径
        String outputVideoUrl="d:\\1.mp4";
        String outputaduioUrl="d:\\2.aac";
        //1.拉取视频
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputUrl);
        grabber.start();

        //2.录制视频
        FFmpegFrameRecorder videoRecorder=new FFmpegFrameRecorder(outputVideoUrl,grabber.getImageWidth(),grabber.getImageHeight());
        videoRecorder.setFrameRate(25);// 设置帧率
        videoRecorder.setGopSize(25);// 设置gop,与帧率相同,相当于间隔1秒chan's一个关键帧
        videoRecorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);  //压缩方式264
        videoRecorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); //视频源数据yuv
        videoRecorder.setVideoOption("threads", "8"); //解码线程数
        videoRecorder.start();

        //3.录制音频
        FFmpegFrameRecorder audioRecorder=new FFmpegFrameRecorder(outputaduioUrl,grabber.getAudioChannels());
        audioRecorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC); //设置音频压缩方式
        audioRecorder.start();

        //读取每一种数据,一帧数据可能是音频或视频
        Frame avFrame=null;
        while((avFrame = grabber.grab())!=null){

            if(avFrame.streamIndex==AVMEDIA_TYPE_VIDEO){ //视频帧
                videoRecorder.record(avFrame); //录制视频
            }else if(avFrame.streamIndex==AVMEDIA_TYPE_AUDIO){  //音频帧
                audioRecorder.record(avFrame); //录制音频
            }

        }

        //关闭相关对象
        grabber.close();
        videoRecorder.close();
        audioRecorder.close();
    }
}

RTMP拉流存储

package com.xl.ffmpeg;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FFmpegLogCallback;
import org.bytedeco.javacv.Frame;


import static org.bytedeco.ffmpeg.global.avutil.*;

public class Test4 {

    public static void main(String[] args) throws Exception {
        //开启日志
        FFmpegLogCallback.set();

        String inputUrl="rtmp://58.200.131.2:1935/livetv/hunanhd";

        //抽取视频和音频存储路径
        String outputVideoUrl="d:\\1.flv";
        //1.拉取视频
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputUrl);
        grabber.setOption("threads", "1");
        // 设置缓存大小,提高画质、减少卡顿花屏
        grabber.setOption("buffer_size", "1024000");
        // 读写超时,适用于所有协议的通用读写超时
        grabber.setOption("rw_timeout", "15000000");
        // 探测视频流信息,为空默认5000000微秒
        grabber.setOption("probesize","15000000");
        // 解析视频流信息,为空默认5000000微秒
        grabber.setOption("analyzeduration", "15000000");
        // rtmp拉流缓冲区,默认3000毫秒
        grabber.setOption("rtmp_buffer", "1000");

        grabber.start();

        //2.录制视频/音频
        FFmpegFrameRecorder recorder=new FFmpegFrameRecorder(outputVideoUrl,grabber.getImageWidth(),grabber.getImageHeight());
        recorder.setFrameRate(25);// 设置帧率
        recorder.setGopSize(25);// 设置gop,与帧率相同,相当于间隔1秒chan's一个关键帧
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);  //压缩方式264
        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); //视频源数据yuv
        recorder.setVideoOption("threads", "8"); //解码线程数
        recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC); //设置音频压缩方式
        recorder.setFormat("flv");
        recorder.start();

        //读取每一种数据,一帧数据可能是音频或视频
        Frame avFrame=null;
        while((avFrame = grabber.grab())!=null){
            recorder.record(avFrame); //录制
        }

        //关闭相关对象
        grabber.close();
        recorder.close();
    }
}

上一篇 下一篇

猜你喜欢

热点阅读