美文网首页
Java后端音视频

Java后端音视频

作者: 何亮hook_8285 | 来源:发表于2021-11-07 00:41 被阅读0次

描述

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

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

核心类

  • FFmpegFrameGrabber 它可以打开本地视频或拉取RTMP流媒体服务器。内部实现FFMPEG中的 解复用->解码->像素转换->重采样等操作

  • FFmpegFrameRecorder 将视频中每一帧数据存储音频或视频数据存储到本地。内部实现FFMPEG中的 复用->编码->封装包->数据到本地

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();
    }
}

相关文章

网友评论

      本文标题:Java后端音视频

      本文链接:https://www.haomeiwen.com/subject/bvvszltx.html