Объединение клипов mp4 с mp4parser делает звук позади видео

Я разрабатываю приложение, которое объединяет клипы mp4 с помощью библиотеки mp4parser (isoparser-1.0-RC-27.jar и aspectjrt-1.8.0.jar). Когда два клипа объединяются, они становятся одним клипом, но по мере добавления к нему большего количества клипов выходной mp4 имеет звук позади видео.

Вот код:

    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);
}

Я предполагаю, что по мере добавления большего количества клипов синхронизация видео и аудио нарушается, поскольку при объединении двух более длинных клипов аудио/видео в порядке. Есть ли способ предотвратить эту плохую синхронизацию видео и аудио в нескольких небольших клипах, или кто-нибудь нашел решение для этого с помощью mp4parser ?? FFMpeg - еще одно решение, которое я рассматриваю, но не нашел, чтобы кто-то еще использовал его для этого.

РЕДАКТИРОВАТЬ: я обнаружил, что звук обычно длиннее, чем видео, поэтому именно это приводит к тому, что финальное результирующее видео смещается так сильно, когда для создания одного клипа добавляется все больше и больше клипов. Я собираюсь решить, обрезав аудиосэмплы


person Lucas Crawford    schedule 15.09.2014    source источник


Ответы (2)


просто поместив код в ответ Лукаса выше:

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);
}
person mt.uulu    schedule 16.06.2016
comment
Всего одно предложение: при расчете продолжительности выборки ее следует разделить на шкалу времени трека, чтобы получить фактическую продолжительность. - person Manish Kumar; 20.12.2017

Я смог исправить эту проблему, используя технику с приведенным выше редактированием. Хитрость заключается в том, чтобы отслеживать, сколько клипов объединяется вместе, и удалять сэмплы с конца звуковой дорожки самого последнего добавленного клипа. Поскольку результирующий выходной mp4 растет с увеличением количества клипов, вам нужно обрезать все больше и больше концов. Частично это связано с разницей во времени аудио- и видеодорожек, поскольку звуковая дорожка может быть 1020 мс, а видео — 1000 мс, при добавлении 5 клипов у вас будет смещение около 100 мс для длины аудио и видео, поэтому вы должны компенсировать это.

person Lucas Crawford    schedule 18.05.2015
comment
Пожалуйста, добавьте код для обрезки звуковых дорожек для других людей, которые найдут ваше решение. Спасибо! - person Episodex; 26.09.2015
comment
Я писал это некоторое время назад, позвольте мне выкопать мое решение - person Lucas Crawford; 26.09.2015
comment
Спасибо за интерес :). Я узнал, как технически обрезать звук, но у меня все еще есть проблема с выбором правильного количества сэмплов для удаления. Мне интересно, нашли ли вы какое-то решение для этого. - person Episodex; 26.09.2015
comment
Проблема в том, что аудио находится в начале видео, поэтому удаление аудиосэмплов не поможет. Это удаление образцов видео, достаточное для синхронизации аудио с видео, но недостаточное для того, чтобы человеческий глаз заметил, что вы это сделали. - person Lucas Crawford; 27.09.2015