【问题标题】:Android merging mp4 and aac file using mediamuxer mediacodec and mediaextractor (without mp4parser)Android使用mediamuxer mediacodec和mediaextractor合并mp4和aac文件(没有mp4parser)
【发布时间】:2017-04-22 12:49:02
【问题描述】:

我正在录制音频,然后尝试合并 aac 音频和 mp4 视频文件(静音,无音频),并共享合并的 mp4 文件。合并后的mp4文件共享在三星J2和小米都可以,但是在联想、Micromax等手机上不能播放mp4文件。这里提到测试结果: https://docs.google.com/spreadsheets/d/1eeJEM-v-smEUzY-bSxwIwFVOsAbv6KT2u3Kz3jdOb8o/edit?usp=sharing 我无法理解问题是由于共享还是由于不正确的复用以及问题的原因是什么。请帮忙。

recordAudio.java 中有共享代码,是这样的:

public void shareVroom(View view) {
//    Toast.makeText(this, "Share feature is temporarily disabled", android.widget.Toast.LENGTH_LONG).show();

//    Toast.makeText(this, "Share feature is enabled", android.widget.Toast.LENGTH_LONG).show();
        // Code commented for UAT

        try {
            MediaMultiplexer mediaMultiplexer = new MediaMultiplexer();
            mediaMultiplexer.startMuxing(this);

            Toast.makeText(this, "in share",Toast.LENGTH_SHORT).show();
            String shareableFileName = "";

            Intent intentShareFile = new Intent(Intent.ACTION_SEND);
            shareableFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
            shareableFileName += getString(R.string.vroom_video_output_file_name);
            File fileWithinMyDir = new File(shareableFileName);
            Uri videoUri=Uri.parse(shareableFileName);
            if (fileWithinMyDir.exists()) {
                intentShareFile.setType("video/mp4");
                intentShareFile.putExtra(Intent.EXTRA_STREAM, videoUri);
                intentShareFile.putExtra(Intent.EXTRA_SUBJECT, "Listen to my VROOM");
                intentShareFile.putExtra(Intent.EXTRA_TEXT, "Vroom attached");
                startActivity(Intent.createChooser(intentShareFile, "Share your Vroom with"));
            }

        } catch (IllegalStateException e) {
            e.printStackTrace();
            Log.e("tag", e.getMessage(), e);
            Toast.makeText(this, "could not shared"+e.getMessage(),Toast.LENGTH_SHORT).show();
        }


        //TODO:Use event to identify if muxing is done

    }

复用代码:

public class MediaMultiplexer {
    private static final int MAX_SAMPLE_SIZE = 256 * 1024;

    public void startMuxing(Context context) {
        MediaMuxer muxer = null;
        MediaFormat VideoFormat = null;
        Resources mResources = context.getResources();
        int sourceVideo = R.raw.vid;
        String outputVideoFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
        outputVideoFileName += context.getString(R.string.vroom_video_output_file_name);
        try {
            muxer = new MediaMuxer(outputVideoFileName, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
        } catch (IOException e) {
            e.printStackTrace();
        }
        MediaExtractor extractorVideo = new MediaExtractor();
        try {
            AssetFileDescriptor srcVideoFd = mResources.openRawResourceFd(sourceVideo);
            extractorVideo.setDataSource(srcVideoFd.getFileDescriptor(), srcVideoFd.getStartOffset(), srcVideoFd.getLength());
            int tracks = extractorVideo.getTrackCount();
            for (int i = 0; i < tracks; i++) {
                MediaFormat mf = extractorVideo.getTrackFormat(i);
                String mime = mf.getString(MediaFormat.KEY_MIME);
                if (mime.startsWith("video/")) {
                    extractorVideo.selectTrack(i);
                    VideoFormat = extractorVideo.getTrackFormat(i);
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        MediaExtractor extractorAudio = new MediaExtractor();
        try {
            String audioFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
            audioFileName += context.getString(R.string.vroom_audio_file_name);
            extractorAudio.setDataSource(audioFileName);
            int tracks = extractorAudio.getTrackCount();
//            Toast.makeText(context, "No of tracks::::" + String.valueOf(tracks), Toast.LENGTH_SHORT).show();
            extractorAudio.selectTrack(0);

            MediaFormat AudioFormat = extractorAudio.getTrackFormat(0);
            int audioTrackIndex = muxer.addTrack(AudioFormat);
            int videoTrackIndex = muxer.addTrack(VideoFormat);

            boolean sawEOS = false;
            boolean sawAudioEOS = false;
            int bufferSize = MAX_SAMPLE_SIZE;
            ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize);
            int offset = 100;
            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
            muxer.start();

            while (!sawEOS) {
                bufferInfo.offset = offset;
                bufferInfo.size = extractorVideo.readSampleData(dstBuf, offset);
                if (bufferInfo.size < 0) {
                    sawEOS = true;
                    bufferInfo.size = 0;
                } else {
                    bufferInfo.presentationTimeUs = extractorVideo.getSampleTime();
                    bufferInfo.flags = extractorVideo.getSampleFlags();
                    int trackIndex = extractorVideo.getSampleTrackIndex();
                    muxer.writeSampleData(videoTrackIndex, dstBuf, bufferInfo);
                    extractorVideo.advance();
                }
            }
            ByteBuffer audioBuf = ByteBuffer.allocate(bufferSize);
            while (!sawAudioEOS) {
                bufferInfo.offset = offset;
                bufferInfo.size = extractorAudio.readSampleData(audioBuf, offset);
                if (bufferInfo.size < 0) {
                    sawAudioEOS = true;
                    bufferInfo.size = 0;
                } else {
                    bufferInfo.presentationTimeUs = extractorAudio.getSampleTime();
                    bufferInfo.flags = extractorAudio.getSampleFlags();
                    int trackIndex = extractorAudio.getSampleTrackIndex();
                    muxer.writeSampleData(audioTrackIndex, audioBuf, bufferInfo);
                    extractorAudio.advance();
                }
            }
            muxer.stop();
            muxer.release();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

}

【问题讨论】:

  • 我修复了你的代码块。在 SO 上格式化代码块的最简单方法是将其粘贴到您的问题中,选择它,然后按 Ctrl+K 或单击 {} 按钮。这会将块缩进另外四个空格,这告诉 Stack Overflow 将其视为代码。您可以在help centre 中阅读有关格式化的更多信息。
  • 下载一个名为mediaInfo的工具并告诉我们编解码器设置。如果视频的 h.264 配置文件为“高”,则它可能无法在某些设备中播放,请使用“基线”以获得最大的设备兼容性。你的音频是 AAC 还是 MP3?还要检查音频的采样率是否为 44.1 千赫兹,是否为立体声等...

标签: android mp4 android-mediacodec mediamuxer mediaextractor


【解决方案1】:

将音频输出格式和编码器更改为 AMR_NB

【讨论】:

    猜你喜欢
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 2021-04-15
    • 2021-08-02
    • 1970-01-01
    • 2014-07-21
    • 1970-01-01
    • 2016-07-08
    相关资源
    最近更新 更多