【问题标题】:Extract Audio from Mp4 and Save to Sd Card (MediaExtractor)从 Mp4 中提取音频并保存到 SD 卡 (MediaExtractor)
【发布时间】:2016-05-24 13:41:48
【问题描述】:

我的 SD 卡中有一个 mp4 视频文件。我想从视频中提取音频,然后使用 MediaExtractor Api 将提取的音频作为单独的文件保存在 sd 卡上。这是我尝试过的代码:

  MediaExtractor extractor = new MediaExtractor();
  extractor.setDataSource(MEDIA_PATH_To_File_On_SDCARD);
  for (i = 0; i < extractor.getTrackCount(); i++) {
            MediaFormat format = extractor.getTrackFormat(i);
            String mime = format.getString(MediaFormat.KEY_MIME);
            if (mime.startsWith("audio/")) {
                extractor.selectTrack(i);
                decoder = MediaCodec.createDecoderByType(mime);

                if(decoder != null)
                {
                   decoder.configure(format, null, null, 0);
                }

                break;
            }
        }

卡在这里我不知道如何获取选定的音轨并将其保存到 sd 卡。

【问题讨论】:

    标签: android android-sdcard android-mediacodec mediamuxer mediaextractor


    【解决方案1】:

    看看我的帖子Decoding Video and Encoding again by Mediacodec gets a corrupted file,里面有一个例子(也请注意答案)。 您必须使用 MediaMuxer,为视频轨道调用 AddTrack,并在编码每一帧后将数据写入该轨道到 muxer。您还必须为音频添加轨道。如果你只想要音频,忽略视频部分,只需将数据保存到与音频相关的复用器中即可。您可以在 grafika 页面中看到一些示例,其中之一可能是:https://github.com/google/grafika/

    您还可以在此处找到更多示例:http://www.bigflake.com/mediacodec/

    谢谢

    【讨论】:

    • 谢谢!,我会试试,告诉你进展如何
    • @donnie 嘿,我正在尝试做类似的事情。你能告诉我从哪里开始或分享一段代码。
    【解决方案2】:

    晚会,这可以通过同时使用MediaExtractorMediaMuxer API 来完成,从下面查看工作 URL,

    /**
         * @param srcPath the path of source video file.
         * @param dstPath the path of destination video file.
         * @param startMs starting time in milliseconds for trimming. Set to
         *            negative if starting from beginning.
         * @param endMs end time for trimming in milliseconds. Set to negative if
         *            no trimming at the end.
         * @param useAudio true if keep the audio track from the source.
         * @param useVideo true if keep the video track from the source.
         * @throws IOException
         */
        @SuppressLint("NewApi")
        public void genVideoUsingMuxer(String srcPath, String dstPath, int startMs, int endMs, boolean useAudio, boolean useVideo) throws IOException {
            // Set up MediaExtractor to read from the source.
            MediaExtractor extractor = new MediaExtractor();
            extractor.setDataSource(srcPath);
            int trackCount = extractor.getTrackCount();
            // Set up MediaMuxer for the destination.
            MediaMuxer muxer;
            muxer = new MediaMuxer(dstPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
            // Set up the tracks and retrieve the max buffer size for selected
            // tracks.
            HashMap<Integer, Integer> indexMap = new HashMap<Integer, Integer>(trackCount);
            int bufferSize = -1;
            for (int i = 0; i < trackCount; i++) {
                MediaFormat format = extractor.getTrackFormat(i);
                String mime = format.getString(MediaFormat.KEY_MIME);
                boolean selectCurrentTrack = false;
                if (mime.startsWith("audio/") && useAudio) {
                    selectCurrentTrack = true;
                } else if (mime.startsWith("video/") && useVideo) {
                    selectCurrentTrack = true;
                }
                if (selectCurrentTrack) {
                    extractor.selectTrack(i);
                    int dstIndex = muxer.addTrack(format);
                    indexMap.put(i, dstIndex);
                    if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
                        int newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
                        bufferSize = newSize > bufferSize ? newSize : bufferSize;
                    }
                }
            }
            if (bufferSize < 0) {
                bufferSize = DEFAULT_BUFFER_SIZE;
            }
            // Set up the orientation and starting time for extractor.
            MediaMetadataRetriever retrieverSrc = new MediaMetadataRetriever();
            retrieverSrc.setDataSource(srcPath);
            String degreesString = retrieverSrc.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
            if (degreesString != null) {
                int degrees = Integer.parseInt(degreesString);
                if (degrees >= 0) {
                    muxer.setOrientationHint(degrees);
                }
            }
            if (startMs > 0) {
                extractor.seekTo(startMs * 1000, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
            }
            // Copy the samples from MediaExtractor to MediaMuxer. We will loop
            // for copying each sample and stop when we get to the end of the source
            // file or exceed the end time of the trimming.
            int offset = 0;
            int trackIndex = -1;
            ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize);
            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
            muxer.start();
            while (true) {
                bufferInfo.offset = offset;
                bufferInfo.size = extractor.readSampleData(dstBuf, offset);
                if (bufferInfo.size < 0) {
                    Log.d(TAG, "Saw input EOS.");
                    bufferInfo.size = 0;
                    break;
                } else {
                    bufferInfo.presentationTimeUs = extractor.getSampleTime();
                    if (endMs > 0 && bufferInfo.presentationTimeUs > (endMs * 1000)) {
                        Log.d(TAG, "The current sample is over the trim end time.");
                        break;
                    } else {
                        bufferInfo.flags = extractor.getSampleFlags();
                        trackIndex = extractor.getSampleTrackIndex();
                        muxer.writeSampleData(indexMap.get(trackIndex), dstBuf, bufferInfo);
                        extractor.advance();
                    }
                }
            }
            muxer.stop();
            muxer.release();
            return;
        }
    

    您可以通过使用单行来使用上述方法: genVideoUsingMuxer(videoFile, originalAudio, -1, -1, true, false)

    另外,阅读 cmets 以更有效地使用此方法。 要点:https://gist.github.com/ArsalRaza/132a6e99d59aa80b9861ae368bc786d0

    【讨论】:

      猜你喜欢
      • 2021-01-07
      • 2017-09-14
      • 2012-03-08
      • 1970-01-01
      • 2018-07-09
      • 2019-01-14
      • 2023-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多