利用javacv实现视频转h264

网上找到的一个实用的视频转换工具类,可将视频转为h264编码(方便在浏览器下播放视频)。

import org.bytedeco.ffmpeg.avcodec.AVCodecParameters;

import org.bytedeco.ffmpeg.avformat.AVFormatContext;

import org.bytedeco.ffmpeg.avformat.AVStream;

import org.bytedeco.ffmpeg.global.avcodec;

import org.bytedeco.javacv.FFmpegFrameGrabber;

import org.bytedeco.javacv.FFmpegFrameRecorder;

import org.bytedeco.javacv.FFmpegLogCallback;

import org.bytedeco.javacv.Frame;

import org.bytedeco.javacv.FrameGrabber;

/**

* 视频工具类

*

* @author alderaan

* @version 创建时间:2022年5月10日 下午3:43:18

*

*/

public class VideoUtil

{

/**

* 视频转码函数(仅转码)

*

* @param inputfile 原始视频文件完整路径

* @param outputfile 目标视频文件完整保存路径(必须完整文件名,即包含格式后缀,推荐格式后缀为.mp4)

* @throws Exception 异常

*/

public static void videoConvert(String inputfile, String outputfile) throws Exception

{

if (outputfile.lastIndexOf('.') < 0)

{

throw new Exception("Error! Output file format undetected!");

}

String format = outputfile.substring(outputfile.lastIndexOf('.'));

FFmpegLogCallback.set();

Frame frame;

FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputfile);

FFmpegFrameRecorder recorder = null;

try

{

System.out.println("开始初始化帧抓取器");

// 初始化帧抓取器,例如数据结构(时间戳、编码器上下文、帧对象等),

// 如果入参等于true,还会调用avformat_find_stream_info方法获取流的信息,放入AVFormatContext类型的成员变量oc中

grabber.start(true);

System.out.println("帧抓取器初始化完成");

// grabber.start方法中,初始化的解码器信息存在放在grabber的成员变量oc中

AVFormatContext avformatcontext = grabber.getFormatContext();

// 文件内有几个媒体流(一般是视频流+音频流)

int streamNum = avformatcontext.nb_streams();

// 没有媒体流就不用继续了

if (streamNum < 1)

{

System.out.println("文件内不存在媒体流");

throw new Exception("Error! There is no media stream in the file!");

}

// 取得视频的帧率

double framerate = grabber.getVideoFrameRate();

System.out.println("videocodec:" + grabber.getVideoMetadata());

System.out.printf("视频帧率[%f],视频时长[%d]秒,媒体流数量[%d]\r\n", framerate, avformatcontext.duration() / 1000000,

avformatcontext.nb_streams());

// 遍历每一个流,检查其类型

for (int i = 0; i < streamNum; i++)

{

AVStream avstream = avformatcontext.streams(i);

AVCodecParameters avcodecparameters = avstream.codecpar();

System.out.printf("流的索引[%d],编码器类型[%d],编码器ID[%d]\r\n", i, avcodecparameters.codec_type(),

avcodecparameters.codec_id());

}

// 视频宽度

int frameWidth = grabber.getImageWidth();

// 视频高度

int frameHeight = grabber.getImageHeight();

// 音频通道数量

int audiochannels = grabber.getAudioChannels();

System.out.printf("视频宽度[%d],视频高度[%d],音频通道数[%d]\r\n", frameWidth, frameHeight, audiochannels);

recorder = new FFmpegFrameRecorder(outputfile, frameWidth, frameHeight, audiochannels);

recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);

recorder.setFormat(format);

// 使用原始视频的码率,若需要则自行修改码率

recorder.setVideoBitrate(grabber.getVideoBitrate());

// 一秒内的帧数,帧率

recorder.setFrameRate(framerate);

// 两个关键帧之间的帧数

recorder.setGopSize((int)framerate);

// 设置音频通道数,与视频源的通道数相等

recorder.setAudioChannels(grabber.getAudioChannels());

recorder.start();

int videoframenum = 0;

int audioframenum = 0;

int dataframenum = 0;

// 持续从视频源取帧

while (null != (frame = grabber.grab()))

{

// 有图像,就把视频帧加一

if (null != frame.image)

{

videoframenum++;

// 取出的每一帧,都保存到视频

recorder.record(frame);

}

// 有声音,就把音频帧加一

if (null != frame.samples)

{

audioframenum++;

// 取出的每一帧,都保存到视频

recorder.record(frame);

}

// 有数据,就把数据帧加一

if (null != frame.data)

{

dataframenum++;

}

}

System.out.printf("转码完成,视频帧[%d],音频帧[%d],数据帧[%d]\r\n", videoframenum, audioframenum, dataframenum);

} catch (Exception e)

{

// e.printStackTrace();

throw e;

} finally

{

if (recorder != null)

{

try

{

recorder.close();

} catch (Exception e)

{

// System.out.println("recorder.close异常" + e);

throw e;

}

}

try

{

grabber.close();

} catch (FrameGrabber.Exception e)

{

// System.out.println("frameGrabber.close异常" + e);

throw e;

}

}

}

}

相关推荐
努力还债的学术吗喽1 天前
ffmpeg离线安装到服务器:解决conda/sudo/无法安装的通用方案
服务器·ffmpeg·conda
zymill2 天前
hysAnalyser --- UDP实时流分析使用指南
ffmpeg·ts流分析·mpegts·音视频分析·数字电视流录制·audio vivid·视频分析工具
Everbrilliant892 天前
FFmpeg解码音频数据AudioTrack/OpenSL播放
ffmpeg·音视频·audiotrack·opensl·ffmpeg音频解码播放·decodethread·opensl播放与解码同步
小柯博客4 天前
STM32MP1 没有硬件编解码,如何用 CPU 实现 H.264 编码支持 WebRTC?
c语言·stm32·嵌入式硬件·webrtc·h.264·h264·v4l2
海南java第二人5 天前
数据库范式详解:从冗余到规范的升华之旅
数据库·oracle·ffmpeg
mortimer5 天前
只需三步,动手搭建一个本地免费【实时语音转录】工具WhisperLiveKit
ffmpeg·github·openai
Hi202402177 天前
消除FFmpeg库的SONAME依赖
linux·ffmpeg
广东数字化转型7 天前
JT808,JT1078 —— AAC编码 —— 部标机语音对讲Java实现
aac·h264·h265·g711a·部标机
mortimer9 天前
使用阿里AI模型去除背景噪音:单文件40行代码实现
python·ffmpeg·阿里巴巴
今天也想MK代码9 天前
WebRtc语音通话前置铃声处理
ffmpeg·webrtc