2014-09-15 12 views
5

Tôi đang phát triển một ứng dụng kết hợp các clip mp4 bằng thư viện mp4parser (isoparser-1.0-RC-27.jar và aspectjrt-1.8.0.jar). Khi hai clip được hợp nhất, chúng sẽ trở thành một clip duy nhất nhưng khi nhiều clip được thêm vào nó, mp4 đầu ra có âm thanh đằng sau video.Hợp nhất các clip mp4 với mp4parser làm cho âm thanh phía sau video

Đây là mã:

Movie[] clips = new Movie[2]; 

    //location of the movie clip storage 
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
      Environment.DIRECTORY_PICTURES), "TestMerge"); 

    //Build the two clips into movies 
    Movie firstClip = MovieCreator.build(first); 
    Movie secondClip = MovieCreator.build(second); 

    //Add both movie clips 
    clips[0] = firstClip; 
    clips[1] = secondClip; 

    //List for audio and video tracks 
    List<Track> videoTracks = new LinkedList<Track>(); 
    List<Track> audioTracks = new LinkedList<Track>(); 

    //Iterate all the movie clips and find the audio and videos 
    for (Movie movie: clips) { 
     for (Track track : movie.getTracks()) { 
      if (track.getHandler().equals("soun")) 
       audioTracks.add(track);     
      if (track.getHandler().equals("vide")) 
       videoTracks.add(track); 
     } 
    } 

    //Result movie from putting the audio and video together from the two clips 
    Movie result = new Movie(); 

    //Append all audio and video 
    if (videoTracks.size() > 0) 
     result.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()]))); 

    if (audioTracks.size() > 0) 
     result.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()]))); 

    //Output the resulting movie to a new mp4 file 
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
    String outputLocation = mediaStorageDir.getPath()+timeStamp; 
    Container out = new DefaultMp4Builder().build(result); 
    FileChannel fc = new RandomAccessFile(String.format(outputLocation), "rw").getChannel(); 
    out.writeContainer(fc); 
    fc.close(); 

    //Now set the active URL to play as the combined videos! 
    setURL(outputLocation); 
} 

đoán của tôi là khi có thêm clip đang được thêm vào, đồng bộ hóa video sang âm thanh đang được điều sai lầm, vì nếu hai còn clip được sáp nhập thì audio/video Ổn. Có anyway để ngăn chặn đồng bộ nghèo của video và âm thanh trong nhiều clip nhỏ hơn, hoặc có ai tìm thấy một giải pháp để làm như vậy bằng cách sử dụng mp4parser ?? FFMpeg là một giải pháp khác mà tôi đang xem xét, nhưng chưa tìm thấy ai khác sử dụng nó để làm điều này

EDIT: Tôi đã phát hiện ra rằng âm thanh thường dài hơn video, do đó, đây là nguyên nhân gây ra video cuối cùng được bù đắp quá nhiều khi càng có nhiều clip được thêm vào để tạo một clip. Tôi sẽ giải quyết bằng cách cắt bỏ các mẫu âm thanh

Trả lời

0

Tôi đã có thể khắc phục sự cố này bằng cách sử dụng kỹ thuật có chỉnh sửa ở trên. Bí quyết là để theo dõi bao nhiêu clip đang được sáp nhập với nhau, và loại bỏ các mẫu từ cuối của track âm thanh của clip gần đây nhất được thêm vào. Khi kết quả đầu ra mp4 phát triển với nhiều clip hơn, bạn cần phải tước nhiều hơn và nhiều hơn nữa cuối cùng. Điều này một phần là do sự khác biệt về thời gian của bản âm thanh và video, vì bản âm thanh có thể là 1020 m và video là 1000 mili giây, với 5 clip được thêm vào, bạn sẽ có độ lệch khoảng 100ms cho độ dài âm thanh và video bạn phải đền bù cho điều đó.

+0

Vui lòng thêm mã cho cắt xén các track âm thanh cho người khác mà tìm giải pháp của bạn. Cảm ơn! – Episodex

+0

Tôi đã viết điều này một thời gian trước đây, hãy để tôi đào giải pháp của tôi –

+0

Cảm ơn bạn đã quan tâm :). Tôi đã tìm ra cách cắt âm thanh kỹ thuật, nhưng vẫn gặp sự cố khi chọn đúng số lượng mẫu cần xóa. Tôi tự hỏi nếu bạn đã tìm thấy một số giải pháp này. – Episodex

1

chỉ cần đặt một mã để câu trả lời của Lucas trên:

1.

LinkedList<Track> videoTracks = new LinkedList<>(); 
      LinkedList<Track> audioTracks = new LinkedList<>(); 
      double[] audioDuration = {0}, videoDuration = {0}; 
      for (Movie m : clips) { 
       for (Track t : m.getTracks()) { 
        if (t.getHandler().equals("soun")) { 
         for (long a : t.getSampleDurations()) audioDuration[0] += ((double) a)/t.getTrackMetaData().getTimescale(); 
         audioTracks.add(t); 
        } else if (t.getHandler().equals("vide")) { 
         for (long v : t.getSampleDurations()) videoDuration[0] += ((double) v)/t.getTrackMetaData().getTimescale(); 
         videoTracks.add(t); 
        } 
       } 

       adjustDurations(videoTracks, audioTracks, videoDuration, audioDuration); 
      } 

2.

private void adjustDurations(LinkedList<Track> videoTracks, LinkedList<Track> audioTracks, double[] videoDuration, double[] audioDuration) { 
    double diff = audioDuration[0] - videoDuration[0]; 

    //nothing to do 
    if (diff == 0) { 
     return; 
    } 

    //audio is longer 
    LinkedList<Track> tracks = audioTracks; 

    //video is longer 
    if (diff < 0) { 
     tracks = videoTracks; 
     diff *= -1; 
    } 

    Track track = tracks.getLast(); 
    long[] sampleDurations = track.getSampleDurations(); 
    long counter = 0; 
    for (int i = sampleDurations.length - 1; i > -1; i--) { 
     if (((double) (sampleDurations[i])/track.getTrackMetaData().getTimescale()) > diff) { 
      break; 
     } 
     diff -= ((double) (sampleDurations[i])/track.getTrackMetaData().getTimescale()); 
     audioDuration[0] -= ((double) (sampleDurations[i])/track.getTrackMetaData().getTimescale()); 
     counter++; 
    } 

    if (counter == 0) { 
     return; 
    } 

    track = new CroppedTrack(track, 0, track.getSamples().size() - counter); 

    //update the original reference 
    tracks.removeLast(); 
    tracks.addLast(track); 
} 
+0

Chỉ một gợi ý, trong khi tính toán thời lượng mẫu, nó phải được chia theo thang thời gian theo dõi để có thời lượng thực tế. –

Các vấn đề liên quan