分享

Android音频开发之视频音频视频分离与合成

 ada_lib 2018-03-27

本文主要记录java层视频的音频轨和视频轨分离与合成

主要是使用Google提供给我们的方法MediaExtractor:分离音频视频  MediaMuxer:合成音频视频

直接上测试代码 : 分离音频轨,分离视频轨 合成音频视频

  1. import android.media.MediaCodec;  
  2. import android.media.MediaExtractor;  
  3. import android.media.MediaFormat;  
  4. import android.media.MediaMuxer;  
  5. import android.os.Environment;  
  6. import android.support.v7.app.AppCompatActivity;  
  7. import android.os.Bundle;  
  8. import android.util.Log;  
  9. import android.view.View;  
  10. import android.widget.Button;  
  11.   
  12. import java.io.File;  
  13. import java.io.FileOutputStream;  
  14. import java.io.IOException;  
  15. import java.nio.ByteBuffer;  
  16.   
  17. /**  
  18.  * MediaExtractor and MediaMuxer  
  19.  * Created by slack on 2016/12/30 19:03.  
  20.  */  
  21. public class MainActivity extends AppCompatActivity {  
  22.   
  23.     private static final String SDCARD_PATH = Environment.getExternalStorageDirectory().getPath();  
  24.   
  25.     private Button exactorBtn;  
  26.     private Button muxerBtn;  
  27.     private Button muxerAudioBtn;  
  28.     private Button combineVideoBtn;  
  29.   
  30.     private MediaExtractor mediaExtractor;  
  31.     private MediaMuxer mediaMuxer;  
  32.   
  33.     @Override  
  34.     protected void onCreate(Bundle savedInstanceState) {  
  35.         super.onCreate(savedInstanceState);  
  36.         setContentView(R.layout.activity_main);  
  37.         exactorBtn = (Button) findViewById(R.id.exactor);  
  38.         muxerBtn = (Button) findViewById(R.id.muxer);  
  39.         muxerAudioBtn = (Button) findViewById(R.id.muxer_audio);  
  40.         combineVideoBtn = (Button) findViewById(R.id.combine_video);  
  41.   
  42.         exactorBtn.setOnClickListener(new View.OnClickListener() {  
  43.             @Override  
  44.             public void onClick(View v) {  
  45.                 exactorMedia();  
  46.             }  
  47.         });  
  48.         muxerBtn.setOnClickListener(new View.OnClickListener() {  
  49.             @Override  
  50.             public void onClick(View v) {  
  51.                 muxerMedia();  
  52.             }  
  53.         });  
  54.         muxerAudioBtn.setOnClickListener(new View.OnClickListener() {  
  55.             @Override  
  56.             public void onClick(View v) {  
  57.                 muxerAudio();  
  58.             }  
  59.         });  
  60.   
  61.         combineVideoBtn.setOnClickListener(new View.OnClickListener() {  
  62.             @Override  
  63.             public void onClick(View v) {  
  64.                 combineVideo();  
  65.             }  
  66.         });  
  67.         mediaExtractor = new MediaExtractor();  
  68.     }  
  69.   
  70.     /**  
  71.      * 根据 mime 分离 视频的 音频轨和视频轨  
  72.      */  
  73.     private void exactorMedia() {  
  74.         FileOutputStream videoOutputStream = null;  
  75.         FileOutputStream audioOutputStream = null;  
  76.         try {  
  77.             File videoFile = new File(SDCARD_PATH, "output_video.mp4");  
  78.             if (!videoFile.exists()) {  
  79.                 videoFile.createNewFile();  
  80.             }  
  81.   
  82.             File audioFile = new File(SDCARD_PATH, "output_audio");  
  83.             videoOutputStream = new FileOutputStream(videoFile);  
  84.             audioOutputStream = new FileOutputStream(audioFile);  
  85.             mediaExtractor.setDataSource(SDCARD_PATH + "/input.mp4");  
  86.             int trackCount = mediaExtractor.getTrackCount();  
  87.             int audioTrackIndex = -1;  
  88.             int videoTrackIndex = -1;  
  89.             for (int i = 0; i < trackCount; i++) {  
  90.                 MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);  
  91.                 Log.e("fuck", trackFormat.toString());  
  92.                 String mineType = trackFormat.getString(MediaFormat.KEY_MIME);  
  93.   
  94.                 if (mineType.startsWith("video/")) {  
  95.                     videoTrackIndex = i;  
  96.   
  97.                 }  
  98.   
  99.                 if (mineType.startsWith("audio/")) {  
  100.                     audioTrackIndex = i;  
  101.                 }  
  102.             }  
  103.   
  104.             ByteBuffer byteBuffer = ByteBuffer.allocate(500 * 1024);  
  105.             mediaExtractor.selectTrack(videoTrackIndex);  
  106.             while (true) {  
  107.                 int readSampleCount = mediaExtractor.readSampleData(byteBuffer, 0);  
  108.                 if (readSampleCount < 0) {  
  109.                     break;  
  110.                 }  
  111.   
  112.                 byte[] buffer = new byte[readSampleCount];  
  113.                 byteBuffer.get(buffer);  
  114.                 videoOutputStream.write(buffer);  
  115.                 byteBuffer.clear();  
  116.                 mediaExtractor.advance(); // “快进”到指定帧  
  117.             }  
  118.   
  119.             mediaExtractor.selectTrack(audioTrackIndex);  
  120.             while (true) {  
  121.                 int readSampleCount = mediaExtractor.readSampleData(byteBuffer, 0);  
  122.                 if (readSampleCount < 0) {  
  123.                     break;  
  124.                 }  
  125.   
  126.                 byte[] buffer = new byte[readSampleCount];  
  127.                 byteBuffer.get(buffer);  
  128.                 audioOutputStream.write(buffer);  
  129.                 byteBuffer.clear();  
  130.                 mediaExtractor.advance();  
  131.             }  
  132.   
  133.             Log.e("fuck", "finish");  
  134.         } catch (IOException e) {  
  135.             e.printStackTrace();  
  136.         } finally {  
  137.             mediaExtractor.release();  
  138.             try {  
  139.                 videoOutputStream.close();  
  140.             } catch (IOException e) {  
  141.                 e.printStackTrace();  
  142.             }  
  143.         }  
  144.     }  
  145.   
  146.     private void muxerMedia() {  
  147.         mediaExtractor = new MediaExtractor();  
  148.         int videoIndex = -1;  
  149.         try {  
  150.             mediaExtractor.setDataSource(SDCARD_PATH + "/input.mp4");  
  151.             int trackCount = mediaExtractor.getTrackCount();  
  152.             for (int i = 0; i < trackCount; i++) {  
  153.                 MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);  
  154.                 String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);  
  155.                 if (mimeType.startsWith("video/")) {  
  156.                     videoIndex = i;  
  157.                 }  
  158.             }  
  159.   
  160.             mediaExtractor.selectTrack(videoIndex);  
  161.             MediaFormat trackFormat = mediaExtractor.getTrackFormat(videoIndex);  
  162.             mediaMuxer = new MediaMuxer(SDCARD_PATH + "/output_video", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);  
  163.             int trackIndex = mediaMuxer.addTrack(trackFormat);  
  164.             ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 500);  
  165.             MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();  
  166.             mediaMuxer.start();  
  167.             long videoSampleTime;  
  168.             {  
  169.                 mediaExtractor.readSampleData(byteBuffer, 0);  
  170.                 //skip first I frame  
  171.                 if (mediaExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC)  
  172.                     mediaExtractor.advance();  
  173.                 mediaExtractor.readSampleData(byteBuffer, 0);  
  174.                 long firstVideoPTS = mediaExtractor.getSampleTime();  
  175.                 mediaExtractor.advance();  
  176.                 mediaExtractor.readSampleData(byteBuffer, 0);  
  177.                 long SecondVideoPTS = mediaExtractor.getSampleTime();  
  178.                 videoSampleTime = Math.abs(SecondVideoPTS - firstVideoPTS);  
  179.                 Log.d("fuck", "videoSampleTime is " + videoSampleTime);  
  180.             }  
  181.   
  182.             mediaExtractor.unselectTrack(videoIndex);  
  183.             mediaExtractor.selectTrack(videoIndex);  
  184.             while (true) {  
  185.                 int readSampleSize = mediaExtractor.readSampleData(byteBuffer, 0);  
  186.                 if (readSampleSize < 0) {  
  187.                     break;  
  188.                 }  
  189.                 mediaExtractor.advance();  
  190.                 bufferInfo.size = readSampleSize;  
  191.                 bufferInfo.offset = 0;  
  192.                 bufferInfo.flags = mediaExtractor.getSampleFlags();  
  193.                 bufferInfo.presentationTimeUs += videoSampleTime;  
  194.   
  195.                 mediaMuxer.writeSampleData(trackIndex, byteBuffer, bufferInfo);  
  196.             }  
  197.             mediaMuxer.stop();  
  198.             mediaExtractor.release();  
  199.             mediaMuxer.release();  
  200.   
  201.             Log.e("TAG", "finish");  
  202.         } catch (IOException e) {  
  203.             e.printStackTrace();  
  204.         }  
  205.     }  
  206.   
  207.     private void muxerAudio() {  
  208.         mediaExtractor = new MediaExtractor();  
  209.         int audioIndex = -1;  
  210.         try {  
  211.             mediaExtractor.setDataSource(SDCARD_PATH + "/input.mp4");  
  212.             int trackCount = mediaExtractor.getTrackCount();  
  213.             for (int i = 0; i < trackCount; i++) {  
  214.                 MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);  
  215.                 if (trackFormat.getString(MediaFormat.KEY_MIME).startsWith("audio/")) {  
  216.                     audioIndex = i;  
  217.                 }  
  218.             }  
  219.             mediaExtractor.selectTrack(audioIndex);  
  220.             MediaFormat trackFormat = mediaExtractor.getTrackFormat(audioIndex);  
  221.             mediaMuxer = new MediaMuxer(SDCARD_PATH + "/output_audio", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);  
  222.             int writeAudioIndex = mediaMuxer.addTrack(trackFormat);  
  223.             mediaMuxer.start();  
  224.             ByteBuffer byteBuffer = ByteBuffer.allocate(500 * 1024);  
  225.             MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();  
  226.   
  227.             long stampTime = 0;  
  228.             //获取帧之间的间隔时间  
  229.             {  
  230.                 mediaExtractor.readSampleData(byteBuffer, 0);  
  231.                 if (mediaExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {  
  232.                     mediaExtractor.advance();  
  233.                 }  
  234.                 mediaExtractor.readSampleData(byteBuffer, 0);  
  235.                 long secondTime = mediaExtractor.getSampleTime();  
  236.                 mediaExtractor.advance();  
  237.                 mediaExtractor.readSampleData(byteBuffer, 0);  
  238.                 long thirdTime = mediaExtractor.getSampleTime();  
  239.                 stampTime = Math.abs(thirdTime - secondTime);  
  240.                 Log.e("fuck", stampTime + "");  
  241.             }  
  242.   
  243.             mediaExtractor.unselectTrack(audioIndex);  
  244.             mediaExtractor.selectTrack(audioIndex);  
  245.             while (true) {  
  246.                 int readSampleSize = mediaExtractor.readSampleData(byteBuffer, 0);  
  247.                 if (readSampleSize < 0) {  
  248.                     break;  
  249.                 }  
  250.                 mediaExtractor.advance();  
  251.   
  252.                 bufferInfo.size = readSampleSize;  
  253.                 bufferInfo.flags = mediaExtractor.getSampleFlags();  
  254.                 bufferInfo.offset = 0;  
  255.                 bufferInfo.presentationTimeUs += stampTime;  
  256.   
  257.                 mediaMuxer.writeSampleData(writeAudioIndex, byteBuffer, bufferInfo);  
  258.             }  
  259.             mediaMuxer.stop();  
  260.             mediaMuxer.release();  
  261.             mediaExtractor.release();  
  262.             Log.e("fuck", "finish");  
  263.         } catch (IOException e) {  
  264.             e.printStackTrace();  
  265.         }  
  266.     }  
  267.   
  268.     private void combineVideo() {  
  269.         try {  
  270.             MediaExtractor videoExtractor = new MediaExtractor();  
  271.             videoExtractor.setDataSource(SDCARD_PATH + "/output_video");  
  272.             MediaFormat videoFormat = null;  
  273.             int videoTrackIndex = -1;  
  274.             int videoTrackCount = videoExtractor.getTrackCount();  
  275.             for (int i = 0; i < videoTrackCount; i++) {  
  276.                 videoFormat = videoExtractor.getTrackFormat(i);  
  277.                 String mimeType = videoFormat.getString(MediaFormat.KEY_MIME);  
  278.                 if (mimeType.startsWith("video/")) {  
  279.                     videoTrackIndex = i;  
  280.                     break;  
  281.                 }  
  282.             }  
  283.   
  284.             MediaExtractor audioExtractor = new MediaExtractor();  
  285.             audioExtractor.setDataSource(SDCARD_PATH + "/output_audio");  
  286.             MediaFormat audioFormat = null;  
  287.             int audioTrackIndex = -1;  
  288.             int audioTrackCount = audioExtractor.getTrackCount();  
  289.             for (int i = 0; i < audioTrackCount; i++) {  
  290.                 audioFormat = audioExtractor.getTrackFormat(i);  
  291.                 String mimeType = audioFormat.getString(MediaFormat.KEY_MIME);  
  292.                 if (mimeType.startsWith("audio/")) {  
  293.                     audioTrackIndex = i;  
  294.                     break;  
  295.                 }  
  296.             }  
  297.   
  298.             videoExtractor.selectTrack(videoTrackIndex);  
  299.             audioExtractor.selectTrack(audioTrackIndex);  
  300.   
  301.             MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();  
  302.             MediaCodec.BufferInfo audioBufferInfo = new MediaCodec.BufferInfo();  
  303.   
  304.             mediaMuxer = new MediaMuxer(SDCARD_PATH + "/output", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);  
  305.             int writeVideoTrackIndex = mediaMuxer.addTrack(videoFormat);  
  306.             int writeAudioTrackIndex = mediaMuxer.addTrack(audioFormat);  
  307.             mediaMuxer.start();  
  308.             ByteBuffer byteBuffer = ByteBuffer.allocate(500 * 1024);  
  309.             long sampleTime = 0;  
  310.             {  
  311.                 videoExtractor.readSampleData(byteBuffer, 0);  
  312.                 if (videoExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {  
  313.                     videoExtractor.advance();  
  314.                 }  
  315.                 videoExtractor.readSampleData(byteBuffer, 0);  
  316.                 long secondTime = videoExtractor.getSampleTime();  
  317.                 videoExtractor.advance();  
  318.                 long thirdTime = videoExtractor.getSampleTime();  
  319.                 sampleTime = Math.abs(thirdTime - secondTime);  
  320.             }  
  321.             videoExtractor.unselectTrack(videoTrackIndex);  
  322.             videoExtractor.selectTrack(videoTrackIndex);  
  323.   
  324.             while (true) {  
  325.                 int readVideoSampleSize = videoExtractor.readSampleData(byteBuffer, 0);  
  326.                 if (readVideoSampleSize < 0) {  
  327.                     break;  
  328.                 }  
  329.                 videoBufferInfo.size = readVideoSampleSize;  
  330.                 videoBufferInfo.presentationTimeUs += sampleTime;  
  331.                 videoBufferInfo.offset = 0;  
  332.                 videoBufferInfo.flags = videoExtractor.getSampleFlags();  
  333.                 mediaMuxer.writeSampleData(writeVideoTrackIndex, byteBuffer, videoBufferInfo);  
  334.                 videoExtractor.advance();  
  335.             }  
  336.   
  337.             while (true) {  
  338.                 int readAudioSampleSize = audioExtractor.readSampleData(byteBuffer, 0);  
  339.                 if (readAudioSampleSize < 0) {  
  340.                     break;  
  341.                 }  
  342.   
  343.                 audioBufferInfo.size = readAudioSampleSize;  
  344.                 audioBufferInfo.presentationTimeUs += sampleTime;  
  345.                 audioBufferInfo.offset = 0;  
  346.                 audioBufferInfo.flags = videoExtractor.getSampleFlags();  
  347.                 mediaMuxer.writeSampleData(writeAudioTrackIndex, byteBuffer, audioBufferInfo);  
  348.                 audioExtractor.advance();  
  349.             }  
  350.   
  351.             mediaMuxer.stop();  
  352.             mediaMuxer.release();  
  353.             videoExtractor.release();  
  354.             audioExtractor.release();  
  355.         } catch (IOException e) {  
  356.             e.printStackTrace();  
  357.         }  
  358.     }  
  359.   
  360. }  

布局

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas./apk/res/android"  
  3.               xmlns:tools="http://schemas./tools"  
  4.               android:layout_width="match_parent"  
  5.               android:layout_height="match_parent"  
  6.               android:orientation="vertical"  
  7.               android:paddingBottom="@dimen/activity_vertical_margin"  
  8.               android:paddingLeft="@dimen/activity_horizontal_margin"  
  9.               android:paddingRight="@dimen/activity_horizontal_margin"  
  10.               android:paddingTop="@dimen/activity_vertical_margin">  
  11.   
  12.     <Button  
  13.         android:id="@+id/exactor"  
  14.         android:layout_width="wrap_content"  
  15.         android:layout_height="wrap_content"  
  16.         android:text="分离" />  
  17.   
  18.     <Button  
  19.         android:id="@+id/muxer"  
  20.         android:layout_width="wrap_content"  
  21.         android:layout_height="wrap_content"  
  22.         android:text="分离视频" />  
  23.   
  24.     <Button  
  25.         android:id="@+id/muxer_audio"  
  26.         android:layout_width="wrap_content"  
  27.         android:layout_height="wrap_content"  
  28.         android:text="分离音频" />  
  29.   
  30.     <Button android:id="@+id/combine_video"  
  31.             android:layout_height="wrap_content"  
  32.             android:layout_width="wrap_content"  
  33.             android:text="合成视频"/>  
  34.   
  35. </LinearLayout>  

需要权限

  1. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
  2.     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />  


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多