2015-07-08 2 views
4

Спасибо за отличную библиотеку mp4parser, у меня есть несколько запросов, связанных с мультиплексированием аудио-видео.Как объединить аудио- и видеофайлы в android

Мы использовали приведенный ниже код в 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(); 
+0

Любые ошибки в Logcat? –

ответ

0

Кажется, что проблема с именем выходного файла, который является в качестве входных данных. попробуйте изменить имя выходного файла.

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

Спасибо Nawaz, я попробовал вышеуказанный код, но проблема сохраняется, если видео составляет 10 секунд, а аудио - 1 минуту, тогда объединенный файл будет отображаться 1 минута как продолжительность, но мы сможем увидеть только 10 секунд видео и звук не воспроизводится. Так вы пробовали в любое время mp3 парсер ?. это сработало для вас? – Naruto

+0

Я использовал mp4parser для слияния видео, и он отлично поработал для меня. –

+0

О, мужик, ты замечательный, не могли бы вы, пожалуйста, напишите мне пример рабочего проекта в андроиде или, пожалуйста, поделитесь им в коробке с коробкой и дайте мне ссылку yaar, это будет действительно полезно для меня. Пожалуйста, предоставьте мне образец рабочего проекта, который все что я хочу. Пожалуйста, помогите мне. Спасибо – Naruto

0
  1. Мы можем объединить .m4a, .aac, .3gp аудио файлов с .mp4 видеофайлом в андроиде. 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()); 
     } 
    } 
} 
+0

Не совсем уверен, что случилось с этим ответом. Кажется, он работает как ожидалось для меня Я использую отредактированную версию вышеуказанного кода после того, как я объединил несколько видеофайлов в один и несколько аудиофайлов в один. –

0

Я знаю, что я немного опоздал на это, но это будет полезно для кого-то, кто будет нужно это:

маленький совет всегда стараюсь этой вещи, используя 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 - это путь к основному выходному объединенному файлу, который хранится в назначенном месте. вы заходите и проверяете это, играя его в своем видеоплеере.

Счастливое обучение. Не стесняйтесь спрашивать что угодно, если хотите. :)

Смежные вопросы