概要概要
MediaExtractorとMediaMuxerの学習を続けてください。主な機能は、オーディオとビデオの分離と合成です。このブログは、後で忘れた場合に備えて、メモとしてのみ使用されます。
MediaExtractor
このクラスの主な機能は、オーディオデータをビデオデータから分離することです。
メインAPI
方法 | 説明 |
---|---|
setDataSource(String path) | ローカルファイルまたはネットワークファイルのいずれかのソースファイルを設定します |
getTrackCount() | ソースファイルのチャンネル数を取得する |
getTrackFormat(int index) | 指定されたインデックスのチャネル形式を取得します |
getSampleTime() | 現在のサンプルの表示時間をマイクロ秒単位で返します。 |
readSampleData(ByteBuffer byteBuf、int offset) | オフセットに従って、指定されたチャネルのデータをByteBufferに読み込みます |
前進() | 次のフレームのデータを読み取る |
release() | 完了後にリソースを解放する |
MediaMuxer
このグループの主な機能は、オーディオファイルとビデオファイルを生成することです。また、オーディオファイルとビデオファイルを1つのオーディオファイルとビデオファイルに合成することもできます。
メインAPI
方法 | 説明 |
---|---|
MediaMuxer(文字列パス、int形式) | パス:出力ファイルの名前、形式:出力ファイルの形式 |
addTrack(MediaFormat形式) | チャネルを追加するには、MediaCodec.getOutpurForma() またはを使用Extractor.getTrackFormat(int index) して取得するかMediaFormat 、自分で構築することができます |
開始() | ファイルの合成を開始します |
writeSampleData(int trackIndex、ByteBuffer byteBuf、MediaCodec.BufferInfo bufferInfo) | ByteBufferデータをファイルに書き込みます |
やめる() | 合成を停止します |
release() | リソースを解放する |
実際の戦闘
MediaExtractorの使用
private void start() {
FileOutputStream videooutputStream = null;
FileOutputStream audiooutputStream = null;
MediaExtractor mediaExtractor = null;
try {
File videofile = new File("/sdcard/aaapcm/video.mp4");
File audiofile = new File("/sdcard/aaapcm/audio.pcm");
videooutputStream = new FileOutputStream(videofile);
audiooutputStream = new FileOutputStream(audiofile);
mediaExtractor = new MediaExtractor();
//设置源文件
mediaExtractor.setDataSource("/sdcard/aaapcm/text.mp4");
//获取通道数
int trackCount = mediaExtractor.getTrackCount();
int audio = -1;
int video = -1;
for (int i = 0; i < trackCount; i++) {
MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);
String formatString = trackFormat.getString(MediaFormat.KEY_MIME);
Log.d("mmm", formatString);
//视频通道
if (formatString.startsWith("video/")) {
video = i;
Log.d("mmm", "视频" + video);
}
//音频通道
if (formatString.startsWith("audio/")) {
audio = i;
Log.d("mmm", "音频" + audio);
}
}
ByteBuffer byteBuffer = ByteBuffer.allocate(500 * 1024);
//选择视频通道
mediaExtractor.selectTrack(video);
int i;
//拿到视频通道的数据,写入到文件
while ((i = mediaExtractor.readSampleData(byteBuffer, 0)) > 0) {
byte[] bytes = new byte[i];
byteBuffer.get(bytes);
videooutputStream.write(bytes);
byteBuffer.clear();
mediaExtractor.advance();
}
videooutputStream.close();
//选择音频通道
mediaExtractor.selectTrack(audio);
//拿到音频通道的数据并写入文件
while ((i = mediaExtractor.readSampleData(byteBuffer, 0)) > 0) {
byte[] bytes = new byte[i];
byteBuffer.get(bytes);
audiooutputStream.write(bytes);
byteBuffer.clear();
mediaExtractor.advance();
}
audiooutputStream.close();
Log.d("mmm", "分离结束");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (mediaExtractor != null) {
mediaExtractor.release();
}
}
}
コードのこの部分は、主にソースファイルのオーディオとビデオを分離し、2つのファイルに保存するためのものです。分離されたファイルは再生できません。再合成する必要があります。再生可能なオーディオとビデオの分析を続けましょう。
MediaMuxerの使用
これには、MediaMuxerとMediaExtractorを使用する必要があります
ビデオデータを分離して新しいMP4ファイルに合成すると、新しいMP4を再生できます
public void video() {
MediaMuxer mediaMuxer = null;
try {
MediaExtractor mediaExtractor = new MediaExtractor();
//设置源文件
mediaExtractor.setDataSource("/sdcard/aaapcm/text.mp4");
//获取通道数
int trackCount = mediaExtractor.getTrackCount();
int videoTrackindex = -1;
int framerate = -1;
for (int i = 0; i < trackCount; i++) {
MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);
String formatString = trackFormat.getString(MediaFormat.KEY_MIME);
//找到视频通道
if (formatString.startsWith("video/")) {
framerate = trackFormat.getInteger(MediaFormat.KEY_FRAME_RATE);
//选择视频通道
mediaExtractor.selectTrack(i);
//创建MediaMuxer
mediaMuxer = new MediaMuxer("/sdcard/aaapcm/video11.mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
//添加通道
videoTrackindex = mediaMuxer.addTrack(trackFormat);
//开始合成
mediaMuxer.start();
break;
}
}
if (mediaMuxer == null) {
return;
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
bufferInfo.presentationTimeUs = 0;
ByteBuffer byteBuffer = ByteBuffer.allocate(500 * 1024);
int i = 0;
//从源文件读取视频数据
while ((i = mediaExtractor.readSampleData(byteBuffer, 0)) > 0) {
bufferInfo.offset = 0;
bufferInfo.size = i;
bufferInfo.flags = mediaExtractor.getSampleFlags();
bufferInfo.presentationTimeUs += 1000 * 1000 / framerate;
//把读取到的视频数据重新合成到新的文件
mediaMuxer.writeSampleData(videoTrackindex, byteBuffer, bufferInfo);
mediaExtractor.advance();
}
mediaExtractor.release();
mediaMuxer.stop();
mediaMuxer.release();
Log.d("mmm", "分离视频结束");
} catch (IOException e) {
e.printStackTrace();
}
}
オーディオデータを分離して新しいwavファイルに合成すると、新しいwavを再生できます
public void audio() {
MediaMuxer mediaMuxer = null;
try {
MediaExtractor mediaExtractor = new MediaExtractor();
//添加源文件
mediaExtractor.setDataSource("/sdcard/aaapcm/text.mp4");
//获取通道数
int trackCount = mediaExtractor.getTrackCount();
int audioTrackindex = -1;
int framerate = -1;
for (int i = 0; i < trackCount; i++) {
MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);
String formatString = trackFormat.getString(MediaFormat.KEY_MIME);
//找到音频通道
if (formatString.startsWith("audio/")) {
mediaExtractor.selectTrack(i);
//创建MediaMuxer
mediaMuxer = new MediaMuxer("/sdcard/aaapcm/video11.wav", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
//添加通道
audioTrackindex = mediaMuxer.addTrack(trackFormat);
//开始合成
mediaMuxer.start();
}
if (formatString.startsWith("video/")) {
framerate = trackFormat.getInteger(MediaFormat.KEY_FRAME_RATE);
break;
}
}
if (mediaMuxer == null) {
return;
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
bufferInfo.presentationTimeUs = 0;
ByteBuffer byteBuffer = ByteBuffer.allocate(500 * 1024);
int i = 0;
//分离音频数据
while ((i = mediaExtractor.readSampleData(byteBuffer, 0)) > 0) {
bufferInfo.offset = 0;
bufferInfo.size = i;
bufferInfo.flags = mediaExtractor.getSampleFlags();
bufferInfo.presentationTimeUs += 1000 * 1000 / framerate;
//把分离的音频数据合成到新的文件
mediaMuxer.writeSampleData(audioTrackindex, byteBuffer, bufferInfo);
mediaExtractor.advance();
}
mediaExtractor.release();
mediaMuxer.stop();
mediaMuxer.release();
Log.d("mmm", "分离音频结束");
} catch (IOException e) {
e.printStackTrace();
}
}
分離されたビデオファイルとオーディオファイルをオーディオファイルとビデオファイルに再合成します
public void hecheng() {
try {
MediaExtractor videoExtractor = new MediaExtractor();
videoExtractor.setDataSource("/sdcard/aaapcm/video11.mp4");
int trackCount = videoExtractor.getTrackCount();
int framerate = 0;
MediaFormat videotrackFormat = null;
for (int i = 0; i < trackCount; i++) {
videotrackFormat = videoExtractor.getTrackFormat(i);
String formatString = videotrackFormat.getString(MediaFormat.KEY_MIME);
if (formatString.startsWith("video/")) {
videoExtractor.selectTrack(i);
framerate = videotrackFormat.getInteger(MediaFormat.KEY_FRAME_RATE);
}
}
MediaExtractor audioExtractor = new MediaExtractor();
audioExtractor.setDataSource("/sdcard/aaapcm/video11.wav");
MediaFormat audiotrackFormat = null;
int trackCount1 = audioExtractor.getTrackCount();
for (int i = 0; i < trackCount1; i++) {
audiotrackFormat = audioExtractor.getTrackFormat(i);
String formatString = audiotrackFormat.getString(MediaFormat.KEY_MIME);
if (formatString.startsWith("audio/")) {
audioExtractor.selectTrack(i);
}
}
MediaCodec.BufferInfo videobufferInfo = new MediaCodec.BufferInfo();
MediaCodec.BufferInfo audiobufferInfo = new MediaCodec.BufferInfo();
MediaMuxer mediaMuxer = new MediaMuxer("sdcard/aaapcm/hecheng.mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
int writeAudioTrackIndex = mediaMuxer.addTrack(audiotrackFormat);
int writeVideoTrackIndex = mediaMuxer.addTrack(videotrackFormat);
mediaMuxer.start();
ByteBuffer byteBuffer = ByteBuffer.allocate(500 * 1024);
int i;
while ((i = videoExtractor.readSampleData(byteBuffer, 0)) > 0) {
videobufferInfo.size = i;
videobufferInfo.offset = 0;
videobufferInfo.flags = videoExtractor.getSampleFlags();
videobufferInfo.presentationTimeUs += 1000 * 1000 / framerate;
mediaMuxer.writeSampleData(writeVideoTrackIndex, byteBuffer, videobufferInfo);
videoExtractor.advance();
}
while ((i = audioExtractor.readSampleData(byteBuffer, 0)) > 0) {
audiobufferInfo.size = i;
audiobufferInfo.offset = 0;
audiobufferInfo.flags = audioExtractor.getSampleFlags();
audiobufferInfo.presentationTimeUs += 1000 * 1000 / framerate;
mediaMuxer.writeSampleData(writeAudioTrackIndex, byteBuffer, audiobufferInfo);
audioExtractor.advance();
}
videoExtractor.release();
audioExtractor.release();
mediaMuxer.stop();
mediaMuxer.release();
Log.d("mmm", "合成完毕");
} catch (IOException e) {
e.printStackTrace();
}
}
参照
https://blog.csdn.net/zhi184816/article/details/52514138
https://www.cnblogs.com/renhui/p/7478527.html