demo:https://gitee.com/Lemniscate/audio_and_video_demo
粗略分离的逻辑就是
- MediaExtractor 设置数据源
- 得到音频/视频 的轨道在哪一条
- 得到每一帧的时间差
- 用MediaMuxer 生成纯音频/视频
生成纯视频的代码:
private void extractorVideo() {
int videoIndex = -1;
try {
mediaExtractor = new MediaExtractor();
mediaExtractor.setDataSource(inputFilePath); //数据源
int trackCount = mediaExtractor.getTrackCount();
for (int i = 0; i < trackCount; i++) {
MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);
String string = trackFormat.getString(MediaFormat.KEY_MIME);
if (string.startsWith("video/")) {
videoIndex = i;//得到具体轨道
break;
}
}
mediaExtractor.selectTrack(videoIndex);
MediaFormat trackFormat = mediaExtractor.getTrackFormat(videoIndex);
mediaMuxer = new MediaMuxer(outputVideoFilePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
int i = mediaMuxer.addTrack(trackFormat);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024);
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
mediaMuxer.start();
long videoSampleTime;
//获取每一帧的时间
{
mediaExtractor.readSampleData(byteBuffer, 0);
if (mediaExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {
mediaExtractor.advance();
}
mediaExtractor.readSampleData(byteBuffer, 0);
long sampleTime = mediaExtractor.getSampleTime();
mediaExtractor.advance();
mediaExtractor.readSampleData(byteBuffer, 0);
long sampleTime1 = mediaExtractor.getSampleTime();
videoSampleTime = Math.abs(sampleTime - sampleTime1);
}
//重新选择 否则会丢掉上面的三帧
mediaExtractor.unselectTrack(videoIndex);
mediaExtractor.selectTrack(videoIndex);
while (true) {
int data = mediaExtractor.readSampleData(byteBuffer, 0);
if (data < 0) {
break;
}
bufferInfo.size = data;
bufferInfo.offset = 0;
bufferInfo.flags = mediaExtractor.getSampleFlags();
bufferInfo.presentationTimeUs += videoSampleTime;
mediaMuxer.writeSampleData(i, byteBuffer, bufferInfo);
mediaExtractor.advance();
}
Toast.makeText(this, "ok", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
} finally {
mediaExtractor.release();
mediaMuxer.stop();
mediaMuxer.release();
}
}
纯音频:
private void extractorAudio() {
mediaExtractor = new MediaExtractor();
int audioIndex = -1;
try {
mediaExtractor.setDataSource(inputFilePath);
int trackCount = mediaExtractor.getTrackCount();
for (int i = 0; i < trackCount; i++) {
MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);
String string = trackFormat.getString(MediaFormat.KEY_MIME);
if (string.startsWith("audio/")) {
audioIndex = i;
}
}
mediaExtractor.selectTrack(audioIndex);
MediaFormat trackFormat = mediaExtractor.getTrackFormat(audioIndex);
mediaMuxer = new MediaMuxer(outputAudioFilePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
int i = mediaMuxer.addTrack(trackFormat);
mediaMuxer.start();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024);
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
long time;
{
mediaExtractor.readSampleData(byteBuffer, 0);
if (mediaExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {
mediaExtractor.advance();
}
mediaExtractor.readSampleData(byteBuffer, 0);
long sampleTime = mediaExtractor.getSampleTime();
mediaExtractor.advance();
mediaExtractor.readSampleData(byteBuffer, 0);
long sampleTime1 = mediaExtractor.getSampleTime();
mediaExtractor.advance();
time = Math.abs(sampleTime - sampleTime1);
}
mediaExtractor.unselectTrack(audioIndex);
mediaExtractor.selectTrack(audioIndex);
while (true) {
int data = mediaExtractor.readSampleData(byteBuffer, 0);
if (data < 0) {
break;
}
bufferInfo.size = data;
bufferInfo.flags = mediaExtractor.getSampleFlags();
bufferInfo.offset = 0;
bufferInfo.presentationTimeUs += time;
mediaMuxer.writeSampleData(i, byteBuffer, bufferInfo);
mediaExtractor.advance();
}
Toast.makeText(this, "ok", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
} finally {
mediaExtractor.release();
mediaMuxer.stop();
mediaMuxer.release();
}
}
将两个合成的代码也很相似
需要注意的是 音频 视频的帧数时间差要分别算 因为不一定是一致的 不然可能会出问题
一下是代码:
private void mix() {
MediaExtractor videoExtractor = null;
MediaExtractor audioExtractor = null;
MediaMuxer mixMediaMuxer = null;
try {
videoExtractor = new MediaExtractor();
videoExtractor.setDataSource(outputVideoFilePath);
int videoIndex = -1;
MediaFormat videoTrackFormat = null;
int trackCount = videoExtractor.getTrackCount();
for (int i = 0; i < trackCount; i++) {
videoTrackFormat = videoExtractor.getTrackFormat(i);
if (videoTrackFormat.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
videoIndex = i;
}
}
audioExtractor = new MediaExtractor();
audioExtractor.setDataSource(outputAudioFilePath);
int audioIndex = -1;
MediaFormat audioTrackFormat = null;
trackCount = audioExtractor.getTrackCount();
for (int i = 0; i < trackCount; i++) {
audioTrackFormat = audioExtractor.getTrackFormat(i);
if (audioTrackFormat.getString(MediaFormat.KEY_MIME).startsWith("audio/")) {
audioIndex = i;
}
}
videoExtractor.selectTrack(videoIndex);
audioExtractor.selectTrack(audioIndex);
MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();
MediaCodec.BufferInfo audioBufferInfo = new MediaCodec.BufferInfo();
mixMediaMuxer = new MediaMuxer(outputFilePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
int videoTrackIndex = mixMediaMuxer.addTrack(videoTrackFormat);
int audioTrackIndex = mixMediaMuxer.addTrack(audioTrackFormat);
mixMediaMuxer.start();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024);
long videotime;
long audiotime;
{
videoExtractor.readSampleData(byteBuffer, 0);
if (videoExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {
videoExtractor.advance();
}
videoExtractor.readSampleData(byteBuffer, 0);
long sampleTime = videoExtractor.getSampleTime();
videoExtractor.advance();
videoExtractor.readSampleData(byteBuffer, 0);
long sampleTime1 = videoExtractor.getSampleTime();
videoExtractor.advance();
videotime = Math.abs(sampleTime - sampleTime1);
}
{
audioExtractor.readSampleData(byteBuffer, 0);
if (audioExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {
audioExtractor.advance();
}
audioExtractor.readSampleData(byteBuffer, 0);
long sampleTime = audioExtractor.getSampleTime();
audioExtractor.advance();
audioExtractor.readSampleData(byteBuffer, 0);
long sampleTime1 = audioExtractor.getSampleTime();
audioExtractor.advance();
audiotime = Math.abs(sampleTime - sampleTime1);
}
videoExtractor.unselectTrack(videoIndex);
videoExtractor.selectTrack(videoIndex);
while (true) {
int data = videoExtractor.readSampleData(byteBuffer, 0);
if (data < 0) {
break;
}
videoBufferInfo.size = data;
videoBufferInfo.presentationTimeUs += videotime;
videoBufferInfo.offset = 0;
videoBufferInfo.flags = videoExtractor.getSampleFlags();
mixMediaMuxer.writeSampleData(videoTrackIndex, byteBuffer, videoBufferInfo);
videoExtractor.advance();
}
while (true) {
int data = audioExtractor.readSampleData(byteBuffer, 0);
if (data < 0) {
break;
}
audioBufferInfo.size = data;
audioBufferInfo.presentationTimeUs += audiotime;
audioBufferInfo.offset = 0;
audioBufferInfo.flags = audioExtractor.getSampleFlags();
mixMediaMuxer.writeSampleData(audioTrackIndex, byteBuffer, audioBufferInfo);
audioExtractor.advance();
}
Toast.makeText(this, "ok", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (mixMediaMuxer != null) {
mixMediaMuxer.stop();
mixMediaMuxer.release();
}
videoExtractor.release();
audioExtractor.release();
}
}