package com.gluav;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacv.*;
import java.io.File;
import java.io.IOException;
/**
* 录制直播视频到本地
*/
public class RecordLiveVideoThread implements Runnable {
/**
* 流地址 例如:rtmp://58.200.131.2:1935/livetv/hunantv 湖南卫视
*/
private String streamUrl = "";
/**
* 停止录制时长 0为不限制时长
*/
private long timesSec = 0L;
/**
* 视频文件的输出路径
*/
private String outFilePath;
/**
* 录制的视频文件格式(文件后缀名)
*/
private String filenameExtension = "mp4";
/**
* 是否录制音频
*/
private boolean hasAudio = false;
@Override
public void run() {
if (outFilePath == null || outFilePath.length() == 0) {
System.out.println("文件输出路径不能为空。");
return;
}
//根据直播链接实例FFmpeg抓帧器
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(streamUrl);
FFmpegFrameRecorder recorder = null;
try {
grabber.start();
Frame frame = grabber.grabFrame();
while ((frame.imageWidth < 1) && (frame.imageHeight < 1)) {
frame = grabber.grabFrame();
System.out.println("检查 Frame width: " + frame.imageWidth + ", height: " + frame.imageHeight);
}
if (frame != null) {
//保存到本地的文件
File outFile = new File(outFilePath);
//文件不存在 || 文件不是一个普通文件
if (!outFile.exists() || !outFile.isFile()) {
if (!outFile.createNewFile()) {
System.out.println("文件创建失败");
return;
}
}
// 视频输出地址,视频宽分辨率(宽,高),是否录制音频(0:不录制/1:录制)
// recorder = new FFmpegFrameRecorder(outFilePath, frame.imageWidth, frame.imageHeight, hasAudio ? 1 : 0);
recorder = new FFmpegFrameRecorder(outFilePath, frame.imageWidth, frame.imageHeight, hasAudio ? 1 : 0);
// recorder = new FFmpegFrameRecorder(outFilePath, 3840, 2160, hasAudio ? 1 : 0);
//录制的视频格式
recorder.setFormat(filenameExtension);
// 设置视频编码器为H.264
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
// 设置视频帧率为30帧/秒
recorder.setFrameRate(30);
// 设置视频比特率为4K的标准比特率(例如,60Mbps)
recorder.setVideoBitrate(50000000); // 60 Mbps = 60,000 kbps
//开始录制
recorder.start();
// 计算结束时间
long endTime = System.currentTimeMillis() + timesSec * 1000;
// 如果没有到录制结束时间并且获取到了下一帧则继续录制
System.out.println("Frame width: " + frame.imageWidth + ", height: " + frame.imageHeight);
while ((frame != null)) {
recorder.record(frame);
//获取下一帧
frame = grabber.grabFrame();
}
// recorder.record(frame);
}
grabber.stop();
System.out.println("录制完成。");
} catch (IOException e) {
System.out.println("录制出错。");
e.printStackTrace();
} finally {
//停止录制
try {
grabber.stop();
} catch (FrameGrabber.Exception e) {
e.printStackTrace();
}
if (recorder != null) {
try {
recorder.stop();
} catch (FrameRecorder.Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
RecordLiveVideoThread recordVideoThread = new RecordLiveVideoThread();
recordVideoThread.streamUrl = "rtmp://58.200.131.2:1935/livetv/hunantv ";
recordVideoThread.outFilePath = "D:\\livetv_hunantv.mp4";
//最好设置结束时长 如直接停止程序会造成输出文件的损坏无法正常播放
// recordVideoThread.timesSec = 200L;
recordVideoThread.hasAudio = true;
new Thread(recordVideoThread).start();
}
}
<!--直播流转视频-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>4.0.2-1.4.3</version>
</dependency>
<!--这个依赖Linux系统和windows系统有所不同-->
<!-- windows -->
<dependency>
<groupId>com.github.hoary.ffmpeg</groupId>
<artifactId>FFmpeg-windows-x86_64</artifactId>
<version>2.0.1.1</version>
</dependency>
<!-- Linux -->
<!--<dependency>
<groupId>com.github.hoary.ffmpeg</groupId>
<artifactId>FFmpeg-linux-x86_64</artifactId>
<version>2.0.1.1</version>
</dependency>-->