視頻工具類
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 創(chuàng)建時間: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();
// 沒有媒體流就不用繼續(xù)了
if (streamNum < 1)
{
System.out.println("文件內不存在媒體流");
throw new Exception("Error! There is no media stream in the file!");
}
// 取得視頻的幀率
double framerate = grabber.getVideoFrameRate();
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;
// 持續(xù)從視頻源取幀
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;
}
}
}
}
測試類
/**
* 測試類
*
* @author alderaan
* @version 創(chuàng)建時間:2022年5月10日 下午3:47:49
*
*/
public class App
{
public static void main(String[] args)
{
try
{
// videoConvert函數,根據outputfile的格式后綴設置轉碼后的視頻格式,推薦使用mp4格式后綴
VideoUtil.videoConvert("/home/alderaan/test.MOV", "/result.mp4");
} catch (java.lang.Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("執(zhí)行完畢!");
}
}
POM
<!-- Linux x86_64 使用 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.7</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.5.5-1.5.7</version>
<classifier>linux-x86_64-gpu</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.19-1.5.7</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>5.0-1.5.7</version>
<classifier>linux-x86_64-gpl</classifier>
</dependency>
<!-- Windows x86_64 使用 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.5.5-1.5.7</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.19-1.5.7</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>5.0-1.5.7</version>
<classifier>windows-x86_64</classifier>
</dependency>
文章來源地址http://www.zghlxwxcb.cn/news/detail-589353.html
文章來源:http://www.zghlxwxcb.cn/news/detail-589353.html
到了這里,關于JavaCV:將任意視頻轉碼為h264編碼的mp4格式視頻的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!