Androidのオーディオとビデオの学習:MediaExtractorとMediaMuxerの学習

概要概要

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

おすすめ

転載: blog.csdn.net/qq_34760508/article/details/106660782