繁体   English   中英

如何在android中合并音频和视频文件

[英]How to merge audio and video file in android

感谢伟大的mp4parser库,我几乎没有与音频视频复用相关的查询。

我们在 android 中使用了下面的代码并尝试过,但我们没有得到预期的输出,我们在特定目录中保存了一个有效的 mp4 文件并尝试但没有运气。

在这里我们得到合并的音频和视频,但音频被附加到视频中。 并且附加的音频不会播放,而只是增加了视频的宽度。

来自极客的任何帮助。

这是代码,

    File sdCard = Environment.getDataDirectory();

    String videofilepath = Environment.getExternalStorageDirectory().toString()+"/video.mp4";
    String audiofilepath = Environment.getExternalStorageDirectory().toString()+"/audio.aac";
    File file=new File(videofilepath);

    H264TrackImpl h264Track = new H264TrackImpl(new FileDataSourceImpl(videofilepath));
    AACTrackImpl aacTrack = new AACTrackImpl(new FileDataSourceImpl(audiofilepath));

    Movie movie = new Movie();
    movie.addTrack(h264Track);
    movie.addTrack(aacTrack);


    Container mp4file = new DefaultMp4Builder().build(movie);

    FileChannel fc = new FileOutputStream(new File(Environment.getExternalStorageDirectory().toString() + "/video.mp4")).getChannel();
    mp4file.writeContainer(fc);
    fc.close();
  1. 我们可以将.m4a.aac.3gp音频文件与.mp4视频文件在 android 中合并。 2) .mp3音频文件不能与视频文件合并。

以下代码适用于合并.mp4音频和空白视频(无声音):

public class Search extends FragmentActivity implements LoaderCallbacks<Boolean> {

    private final Search self = this;
    private ProgressDialog mProgressDialog;
    VideoView mVideoView;
    ImageView back, next;
    String path;
    String root = Environment.getExternalStorageDirectory().toString();
    String songpath, songname;
    String TAG = "Logcat";
    String[] fileList;

    String audiopath = "/sdcard/dubmash/audio.m4a";
    String videopath = "/sdcard/dubmash/video.`mp4`";
    String output;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.search);

        Intent i = getIntent();
        if (getIntent().getExtras() != null) {
            songpath = i.getStringExtra("songpath");
            songname = i.getStringExtra("songname");
            Log.e("Search Class :song name", songname);
            Log.e("Search Class :song path", songpath);
        }


        mVideoView = (VideoView) findViewById(R.id.videoview);
        root = Environment.getExternalStorageDirectory().toString();

        back = (ImageView) findViewById(R.id.back);
        next = (ImageView) findViewById(R.id.next);
        String audio = audiopath;
        String video = videopath;
        output = "/sdcard/dubmash/" + songname + ".mp4";

        Log.e("FILE", "audio:" + audio + " video:" + video + " out:" + output);

        try {
            mux(video, audio, output);
        } catch (NullPointerException e) {
            Toast.makeText(Search.this, "Please Record Again ", Toast.LENGTH_SHORT).show();
        }

        try {
            //Delete video file
            File file = new File(videopath);
            boolean deleted = file.delete();
            //Delete Audio file
            File files = new File(audiopath);
            boolean deleted1 = files.delete();


            mVideoView.setVideoPath(output);
            mVideoView.requestFocus();
            mVideoView.start();
        } catch (NullPointerException e) {
            Toast.makeText(Search.this, "File Not Find", Toast.LENGTH_SHORT).show();
        }


        Button play = (Button) findViewById(R.id.playvideoplayer);
        play.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {

                mVideoView.setVideoPath(output);
                mVideoView.requestFocus();
                mVideoView.start();

            }
        });

        next.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent i = new Intent(Search.this, HomePage.class);
                i.putExtra("showdubs", "dubs");
                startActivity(i);
                finish();
            }
        });

        back.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent i = new Intent(Search.this, AlbumDetailVideo.class);
                i.putExtra("songpath", songpath);
                i.putExtra("songname", songname);
                startActivity(i);
                finish();
            }
        });

    }

    @Override
    public Loader<Boolean> onCreateLoader(int id, Bundle args) {
        return new EditMovieTask(self, args.getInt("type"));
    }

    @Override
    public void onLoadFinished(Loader<Boolean> loader, Boolean succeed) {
        getSupportLoaderManager().destroyLoader(loader.getId());
        mProgressDialog.dismiss();
    }

    @Override
    public void onLoaderReset(Loader<Boolean> loader) {
    }

    public static class EditMovieTask extends AsyncTaskLoader<Boolean> {

        private int mType;

        public EditMovieTask(Context context, int type) {
            super(context);
            mType = type;
            forceLoad();
        }

        @Override
        public Boolean loadInBackground() {

            switch (mType) {
                case 0:
                    //         return append();
                case 1:
                    //       return crop();
                case 2:
                    //     return subTitle();
            }

            return false;
        }


    }

    public boolean mux(String videoFile, String audioFile, String outputFile) {
        Movie video;
        try {
            video = new MovieCreator().build(videoFile);
            Log.e("Audio Video", "1");
        } catch (RuntimeException e) {
            e.printStackTrace();
            Log.e("Audio Video", "2");
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            Log.e("Audio Video", "3");
            return false;
        }

        Movie audio;
        try {

            audio = new MovieCreator().build(audioFile);
            Log.e("Audio Video", "4");
        } catch (IOException e) {
            e.printStackTrace();
            Log.e("Audio Video", "5");
            return false;
        } catch (NullPointerException e) {
            e.printStackTrace();
            Log.e("Audio Video", "6");
            return false;
        }

        Track audioTrack = audio.getTracks().get(0);
        video.addTrack(audioTrack);

        Container out = new DefaultMp4Builder().build(video);
        Log.e("Audio Video", "8");
        FileOutputStream fos;
        try {
            Log.e("Audio Video", "9");
            fos = new FileOutputStream(outputFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        }
        BufferedWritableFileByteChannel byteBufferByteChannel = new BufferedWritableFileByteChannel(fos);
        try {
            Log.e("Audio Video", "10");
            out.writeContainer(byteBufferByteChannel);
            byteBufferByteChannel.close();
            Log.e("Audio Video", "11");
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private static class BufferedWritableFileByteChannel implements WritableByteChannel {
        //    private static final int BUFFER_CAPACITY = 1000000;
        private static final int BUFFER_CAPACITY = 10000000;

        private boolean isOpen = true;
        private final OutputStream outputStream;
        private final ByteBuffer byteBuffer;
        private final byte[] rawBuffer = new byte[BUFFER_CAPACITY];

        private BufferedWritableFileByteChannel(OutputStream outputStream) {
            this.outputStream = outputStream;
            this.byteBuffer = ByteBuffer.wrap(rawBuffer);
            Log.e("Audio Video", "13");
        }

        @Override
        public int write(ByteBuffer inputBuffer) throws IOException {
            int inputBytes = inputBuffer.remaining();

            if (inputBytes > byteBuffer.remaining()) {
                Log.e("Size ok ", "song size is ok");
                dumpToFile();
                byteBuffer.clear();

                if (inputBytes > byteBuffer.remaining()) {
                    Log.e("Size ok ", "song size is not okssss ok");
                    throw new BufferOverflowException();
                }
            }

            byteBuffer.put(inputBuffer);

            return inputBytes;
        }

        @Override
        public boolean isOpen() {
            return isOpen;
        }

        @Override
        public void close() throws IOException {
            dumpToFile();
            isOpen = false;
        }

        private void dumpToFile() {
            try {
                outputStream.write(rawBuffer, 0, byteBuffer.position());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }


    private void muxing() {

        String outputFile = "";

        try {

            root = Environment.getExternalStorageDirectory().toString();
            String audio = root + "/" + "audio.mp3";
            String video = root + "/" + "rohit.mp4";


            File file = new File(Environment.getExternalStorageDirectory() + File.separator + "final2.mp4");
            file.createNewFile();
            outputFile = file.getAbsolutePath();


            MediaExtractor videoExtractor = new MediaExtractor();
            videoExtractor.setDataSource(video);

            MediaExtractor audioExtractor = new MediaExtractor();
            audioExtractor.setDataSource(audio);

            Log.d(TAG, "Video Extractor Track Count " + videoExtractor.getTrackCount());
            Log.d(TAG, "Audio Extractor Track Count " + audioExtractor.getTrackCount());

            MediaMuxer muxer = new MediaMuxer(outputFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

            videoExtractor.selectTrack(0);
            MediaFormat videoFormat = videoExtractor.getTrackFormat(0);
            int videoTrack = muxer.addTrack(videoFormat);

            audioExtractor.selectTrack(0);
            MediaFormat audioFormat = audioExtractor.getTrackFormat(0);
            int audioTrack = muxer.addTrack(audioFormat);

            Log.d(TAG, "Video Format " + videoFormat.toString());
            Log.d(TAG, "Audio Format " + audioFormat.toString());

            boolean sawEOS = false;
            int frameCount = 0;
            int offset = 100;
            int sampleSize = 256 * 1024;
            ByteBuffer videoBuf = ByteBuffer.allocate(sampleSize);
            ByteBuffer audioBuf = ByteBuffer.allocate(sampleSize);
            MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();
            MediaCodec.BufferInfo audioBufferInfo = new MediaCodec.BufferInfo();


            videoExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
            audioExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);

            muxer.start();

            while (!sawEOS) {
                videoBufferInfo.offset = offset;
                videoBufferInfo.size = videoExtractor.readSampleData(videoBuf, offset);


                if (videoBufferInfo.size < 0 || audioBufferInfo.size < 0) {
                    Log.d(TAG, "saw input EOS.");
                    sawEOS = true;
                    videoBufferInfo.size = 0;

                } else {
                    videoBufferInfo.presentationTimeUs = videoExtractor.getSampleTime();
                    videoBufferInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME;
                    muxer.writeSampleData(videoTrack, videoBuf, videoBufferInfo);
                    videoExtractor.advance();


                    frameCount++;
                    Log.d(TAG, "Frame (" + frameCount + ") Video PresentationTimeUs:" + videoBufferInfo.presentationTimeUs + " Flags:" + videoBufferInfo.flags + " Size(KB) " + videoBufferInfo.size / 1024);
                    Log.d(TAG, "Frame (" + frameCount + ") Audio PresentationTimeUs:" + audioBufferInfo.presentationTimeUs + " Flags:" + audioBufferInfo.flags + " Size(KB) " + audioBufferInfo.size / 1024);

                }
            }

            Toast.makeText(getApplicationContext(), "frame:" + frameCount, Toast.LENGTH_SHORT).show();


            boolean sawEOS2 = false;
            int frameCount2 = 0;
            while (!sawEOS2) {
                frameCount2++;

                audioBufferInfo.offset = offset;
                audioBufferInfo.size = audioExtractor.readSampleData(audioBuf, offset);

                if (videoBufferInfo.size < 0 || audioBufferInfo.size < 0) {
                    Log.d(TAG, "saw input EOS.");
                    sawEOS2 = true;
                    audioBufferInfo.size = 0;
                } else {
                    audioBufferInfo.presentationTimeUs = audioExtractor.getSampleTime();
                    audioBufferInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME;
                    muxer.writeSampleData(audioTrack, audioBuf, audioBufferInfo);
                    audioExtractor.advance();


                    Log.d(TAG, "Frame (" + frameCount + ") Video PresentationTimeUs:" + videoBufferInfo.presentationTimeUs + " Flags:" + videoBufferInfo.flags + " Size(KB) " + videoBufferInfo.size / 1024);
                    Log.d(TAG, "Frame (" + frameCount + ") Audio PresentationTimeUs:" + audioBufferInfo.presentationTimeUs + " Flags:" + audioBufferInfo.flags + " Size(KB) " + audioBufferInfo.size / 1024);

                }
            }

            Toast.makeText(getApplicationContext(), "frame:" + frameCount2, Toast.LENGTH_SHORT).show();

            muxer.stop();
            muxer.release();


        } catch (IOException e) {
            Log.d(TAG, "Mixer Error 1 " + e.getMessage());
        } catch (Exception e) {
            Log.d(TAG, "Mixer Error 2 " + e.getMessage());
        }
    }
}

似乎问题出在作为输入的输出文件名上。 尝试更改输出文件的名称。

FileChannel fc = new FileOutputStream(new File(Environment.getExternalStorageDirectory().toString() + "/video_out.mp4")).getChannel();

我知道我对此有点晚了,但这对需要此功能的人会有所帮助:

一些建议总是尝试使用AsynchTask来处理这些事情,它使您能够在后台处理这些事情,因为它的方法名为doInBackground()好吧,尝试和捕获也是以同样的方式帮助您的好东西。

你的代码有一点变化,实现它,你会得到结果。

File sdCard = Environment.getDataDirectory();

String videofilepath = Environment.getExternalStorageDirectory().toString()+"/video.mp4";
String audiofilepath = Environment.getExternalStorageDirectory().toString()+"/audio.aac";
File file=new File(videofilepath);

Movie videoOutput = null;
Movie audioOutput = null;

try{
            videoOutput = MovieCreator.build(videoFilePath);
            audioOutput = MovieCreator.build(audioFilePath);
        }catch (Exception e){
                e.printStackTrace();
        }

        List<Track> finalTrack = new ArrayList<>();
        for(Track track : videoOutput.getTracks()){
            if(track.getHandler().equals("vide"))
                finalTrack.add(track);
        }

        for(Track track : audioOutput.getTracks()){
            if(track.getHandler().equals("soun"))
                finalTrack.add(track);
        }

        videoOutput.setTracks(finalTrack);

Container mp4file = new DefaultMp4Builder().build(movie);

String filePath = Environment.getExternalStorageDirectory().toString() + "/video.mp4"    

try{
FileChannel fc = new FileOutputStream(new File(filePath)).getChannel();
mp4file.writeContainer(fc);
fc.close();
}catch(Exception e){
   //catch exception 
}
return filePath;

这里的filePath是存放在指定位置的主输出合并文件的路径。 您可以通过在视频播放器中播放来检查它。

快乐学习。 如果你愿意,可以随意询问任何事情。 :)

String videofilepath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/append.mp4";
String audiofilepath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/originalSound.aac";

AACTrackImpl aacTrack = null;
try {
    aacTrack = new AACTrackImpl(new FileDataSourceImpl(audiofilepath));
    Movie countVideo = MovieCreator.build(videofilepath);
    Movie movie = new Movie();
    movie.addTrack(countVideo.getTracks().get(0));
    movie.addTrack(aacTrack);

    Container mp4file = new DefaultMp4Builder().build(movie);

    FileChannel fc = new FileOutputStream(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/video.mp4")).getChannel();
    mp4file.writeContainer(fc);
    fc.close();
} catch (IOException e) {
    e.printStackTrace();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM