一個音視頻文件是由音頻和視頻組成的,咱們能夠經過MediaExtractor、MediaMuxer把音頻或視頻給單獨抽取出來,抽取出來的音頻和視頻能單獨播放; 網絡
MediaExtractor的做用是把音頻和視頻的數據進行分離。ide
主要API介紹:this
使用示例:spa
MediaExtractor extractor = new MediaExtractor(); extractor.setDataSource(...); int numTracks = extractor.getTrackCount(); for (int i = 0; i < numTracks; ++i) { MediaFormat format = extractor.getTrackFormat(i); String mime = format.getString(MediaFormat.KEY_MIME); if (weAreInterestedInThisTrack) { extractor.selectTrack(i); } } ByteBuffer inputBuffer = ByteBuffer.allocate(...) while (extractor.readSampleData(inputBuffer, ...) >= 0) { int trackIndex = extractor.getSampleTrackIndex(); long presentationTimeUs = extractor.getSampleTime(); ... extractor.advance(); } extractor.release(); extractor = null;
MediaMuxer的做用是生成音頻或視頻文件;還能夠把音頻與視頻混合成一個音視頻文件。rest
相關API介紹:code
使用示例:orm
MediaMuxer muxer = new MediaMuxer("temp.mp4", OutputFormat.MUXER_OUTPUT_MPEG_4); // More often, the MediaFormat will be retrieved from MediaCodec.getOutputFormat() // or MediaExtractor.getTrackFormat(). MediaFormat audioFormat = new MediaFormat(...); MediaFormat videoFormat = new MediaFormat(...); int audioTrackIndex = muxer.addTrack(audioFormat); int videoTrackIndex = muxer.addTrack(videoFormat); ByteBuffer inputBuffer = ByteBuffer.allocate(bufferSize); boolean finished = false; BufferInfo bufferInfo = new BufferInfo(); muxer.start(); while(!finished) { // getInputBuffer() will fill the inputBuffer with one frame of encoded // sample from either MediaCodec or MediaExtractor, set isAudioSample to // true when the sample is audio data, set up all the fields of bufferInfo, // and return true if there are no more samples. finished = getInputBuffer(inputBuffer, isAudioSample, bufferInfo); if (!finished) { int currentTrackIndex = isAudioSample ? audioTrackIndex : videoTrackIndex; muxer.writeSampleData(currentTrackIndex, inputBuffer, bufferInfo); } }; muxer.stop(); muxer.release();
public class MainActivity extends AppCompatActivity { private static final String SDCARD_PATH = Environment.getExternalStorageDirectory().getPath(); private MediaExtractor mMediaExtractor; private MediaMuxer mMediaMuxer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 獲取權限 int checkWriteExternalPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); int checkReadExternalPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);if (checkWriteExternalPermission != PackageManager.PERMISSION_GRANTED || checkReadExternalPermission != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 0); } setContentView(R.layout.activity_main); new Thread(new Runnable() { @Override public void run() { try { process(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } private boolean process() throws IOException { mMediaExtractor = new MediaExtractor(); mMediaExtractor.setDataSource(SDCARD_PATH + "/ss.mp4"); int mVideoTrackIndex = -1; int framerate = 0; for (int i = 0; i < mMediaExtractor.getTrackCount(); i++) { MediaFormat format = mMediaExtractor.getTrackFormat(i); String mime = format.getString(MediaFormat.KEY_MIME); if (!mime.startsWith("video/")) { continue; } framerate = format.getInteger(MediaFormat.KEY_FRAME_RATE); mMediaExtractor.selectTrack(i); mMediaMuxer = new MediaMuxer(SDCARD_PATH + "/ouput.mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); mVideoTrackIndex = mMediaMuxer.addTrack(format); mMediaMuxer.start(); } if (mMediaMuxer == null) { return false; } MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); info.presentationTimeUs = 0; ByteBuffer buffer = ByteBuffer.allocate(500 * 1024); int sampleSize = 0; while ((sampleSize = mMediaExtractor.readSampleData(buffer, 0)) > 0) { info.offset = 0; info.size = sampleSize; info.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME; info.presentationTimeUs += 1000 * 1000 / framerate; mMediaMuxer.writeSampleData(mVideoTrackIndex, buffer, info); mMediaExtractor.advance(); } mMediaExtractor.release(); mMediaMuxer.stop(); mMediaMuxer.release(); return true; } }