MediaExtractor和MediaMuxer使用
MediaExtractor简介
MediaExtractor用来把视频和音频的数据进行分离
对于一个常见的视频文件,通常有一个视频轨道,和一个音频轨道,通过MediaExtractor来分离音视频轨道数据
MediaExtractor使用
常用API
- setDataSource(String path) 设置数据源(本地路径或网络播放地址)
- getTrackCount() 获取源文件轨道数
- getTrackFormat(int index) 获取指定(index)的轨道格式
- selectTrack(int index) 指定当前(index)轨道
- readSampleData(ByteBuffer byteBuf,int offset) 指定偏移量获取当前轨道样本数据
- getSampleTime() 获取当前样本时间戳
- advance() 下一帧
- release() 释放资源
通过以上api我们来获取指定路径视频文件的音轨和视轨
String path = "xxx路径下的文件.mp4";
MediaExtractor mediaExtractor = new MediaExtractor();
try{
mediaExtractor.setDataSource(path);
}catch(Exception e){
}
if(mediaExtractor == null) return;
int trackCount = mediaExtractor.getTrackCount();
for(int i = 0; i < trackCount; i++){
MediaFormat format = mediaExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if(mime.startsWith("video/")){
// 指定当前视频轨道
mediaExtractor.selectTrack(i);
break;
}
// 同理以下代码可以获取音轨
if(mime.startsWith("audio/")){
// 指定当前音频轨道
mediaExtractor.selectTrack(i);
break;
}
}
MediaMuxer简介
MediaMuxer用来生成音频或视频文件,或者把音频和视频混合成一个音视频文件
MediaMuxer使用
常用API
- 构造方法MediaMuxer(String path,int format) path输出文件的路径,format输出文件的格式,当前只支持MP4格式
- addTrack(MediaFormat format) 添加音频或者视频轨道
- start() 开始合成文件
- writeSampleData(int tranckIndex,ByteBuffer byteBuf,MediaCodec.BufferInfo bufferInfo) 把byteBuf中的数据写入到构造器中设置的输出文件中
- stop 停止合成文件
- release 释放资源
结合MediaExtractor和MediaMuxer来将音视频文件分离为一个单独只有视频没有音轨的文件
String inPath = "音视频文件.mp4";
String outPath = "输出只有视频.mp4";
File outFile = new File(outPath);
if(!outFile.exists()){
try(
outFile.createNewFile();
)catch(Exception e){
}
}
MediaExtractor mediaExtractor = new MediaExtractor();
try {
mediaExtractor.setDataSource(inPath);
} catch (Exception e) {
e.printStackTrace();
}
MediaMuxer mediaMuxer = null;
try {
mediaMuxer = new MediaMuxer(outPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
} catch (Exception e) {
e.printStackTrace();
}
int trackIndex = 0;
int trackCount = mediaExtractor.getTrackCount();
for (int i = 0; i < trackCount; i++) {
MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);
String mime = trackFormat.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
trackIndex = mediaMuxer.addTrack(trackFormat);
mediaExtractor.selectTrack(i);
break;
}
}
mediaMuxer.start();
ByteBuffer buffer = ByteBuffer.allocate(1024 * 1000);
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
long videoSampleTime = getSampleTime(mediaExtractor, buffer);
while (true) {
int readSampleDataSize = mediaExtractor.readSampleData(buffer, 0);
if (readSampleDataSize < 0) {
break;
}
bufferInfo.size = readSampleDataSize;
bufferInfo.offset = 0;
bufferInfo.flags = mediaExtractor.getSampleFlags();
bufferInfo.presentationTimeUs += videoSampleTime;
mediaMuxer.writeSampleData(trackIndex, buffer, bufferInfo);
mediaExtractor.advance();
}
mediaExtractor.release();
mediaMuxer.stop();
mediaMuxer.release();
// 获取样本时间
private static long getSampleTime(MediaExtractor mediaExtractor, ByteBuffer buffer) {
long videoSampleTime;
mediaExtractor.readSampleData(buffer, 0);
long firstVideoPTS = mediaExtractor.getSampleTime();
mediaExtractor.advance();
mediaExtractor.readSampleData(buffer, 0);
long secondVideoPTS = mediaExtractor.getSampleTime();
videoSampleTime = Math.abs(secondVideoPTS - firstVideoPTS);
return videoSampleTime;
}
文件路径这里面需要定义真实存在的视频文件路径,代码运行成功,会生成没有音轨的视频文件,播放生成的文件,验证是否成功分离只有视频文件。