транскодирование ffmpeg сбрасывает время начала файла - PullRequest
11 голосов
/ 07 марта 2012

Я использую сегментатор, чтобы сегментировать мой файл MPEG 2 Ts в серию медиа-сегмента для потоковой передачи HTTP

и время начала каждого сегмента, следующее за предыдущим (например: время начала сегментов: 00:00, 00: 10,00: 20,00: 30, ...)

(в Ubuntu)

Вопрос:

Когда я использую ffmpeg для транскодирования одногомультимедийного сегмента (например, от 800 кбит / с до 200 кбит / с)

время начала транскодированного мультимедийного сегмента будет сброшено до 0

ex: при перекодировании третьего сегмента,

время начала смены сегментов на: 00: 00,00: 10, 00: 00 , 00: 30, ...

Это причинамой плеер зависает после воспроизведения транскодированного медиа-сегмента

Есть ли какое-либо решение для перекодирования медиа-файла с тем же временем запуска?

Я полагаю, это ffmpeg, сбросивший PTS (метка времени презентации)сегмента

Но я не знаю, как это исправить ...

вот моя команда ffmpeg (транскодировать до 250 Кбит / с)

знак равно===========================

ffmpeg -y -i sample-03.ts -f mpegts -acodec libfaac -ar 48000 -ab 64k -vcodec libx264 -b 250k -flags +loop -cmp +chroma \
 -partitions +parti4x4+partp8x8+partb8x8 -subq 7 -trellis 0 -refs 0 -coder 0 -me_range 16 -keyint_min 25 \
 -sc_threshold 40 -i_qfactor 0.71 -maxrate 250k -bufsize 250k -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 \
 -qmin 10 -qmax 51 -qdiff 4 -level 30 -aspect 320:240 -g 30 -async 2 sample.ts

============================

Помогите!

спасибо

Ответы [ 5 ]

3 голосов
/ 10 марта 2013

прямое смещение времени пакетов в кодированных сегментах h264

В итоге я соединился с библиотеками ffmpeg libavformat / avcodec для чтения и непосредственно сдвинул заголовки времени пакетов.Время смещения указывается в секундах

unsigned int tsShift = offsetTime * 90000; // h264 defined sample rate is 90khz

и далее ниже

do {
    double segmentTime;
    AVPacket packet;

    decodeDone = av_read_frame(pInFormatCtx, &packet);
    if (decodeDone < 0) {
        break;
    }

    if (av_dup_packet(&packet) < 0) {
        cout << "Could not duplicate packet" << endl;
        av_free_packet(&packet);
        break;
    }

    if (packet.stream_index == videoIndex && (packet.flags & AV_PKT_FLAG_KEY)) {
        segmentTime = (double)pVideoStream->pts.val * pVideoStream->time_base.num / pVideoStream->time_base.den;
    }
    else if (videoIndex < 0) {
        segmentTime = (double)pAudioStream->pts.val * pAudioStream->time_base.num / pAudioStream->time_base.den;
    }
    else {
        segmentTime = prevSegmentTime;
    }

    // cout << "before packet pts dts " << packet.pts << " " << packet.dts;
    packet.pts += tsShift;
    packet.dts += tsShift;
    // cout << " after packet pts dts " << packet.pts << " " << packet.dts << endl;


    ret = av_interleaved_write_frame(pOutFormatCtx, &packet);
    if (ret < 0) {
        cout << "Warning: Could not write frame of stream" << endl;
    }
    else if (ret > 0) {
        cout <<  "End of stream requested" << endl;
        av_free_packet(&packet);
        break;
    }

    av_free_packet(&packet);

} while (!decodeDone);

мегапикселей источника сдвига


сдвинутых потоков в раундео способе

но дельта времени не совсем то, что я указываю

Вот как

  1. сначала преобразовать исходный файл TS в необработанный формат

    ffmpeg -i original.ts original.avi

  2. применить фильтр setpts и преобразовать в кодированный формат (это будет отличаться в зависимости от частоты кадров и требуемого временного сдвига)

    ffmpeg -i original.avi -filter: v 'setpts = 240 + PTS' -sameq -vcodec libx264 shift.mp4

  3. сегментировать результирующий сдвиг.mp4

    ffmpeg -i shift.mp4 -qscale 0 -bsf: v h264_mp4toannexb -vcodec copy -an -map 0 -f сегмент -segment_time 10 -segment_format mpegts -y ./temp-%03d.ts

последний созданный файл сегмента, в моем случае temp-001.ts, был сдвинут во времени

проблема: этот метод кажется тупым для мСдвиг некоторых времен TS в пакетное время привел к тому, что время начала 10,5+ вместо 10 секунд, требуемых для нового файла TS


, исходное предложение не работало, как описано ниже

ffmpeg -itoffset prevTime (rest of ts gen args) | ffmpeg -ss prevTime -i _ -t 10 stuff.ts

prevTime - длительность всех предыдущих сегментов.

не годится, так как второй вызов ffmpeg -ss делает выходной файл mpegts относительно времени 0 (или иногда 1.4сек - возможно, ошибка в построении одиночногоTS файлы)

2 голосов
/ 15 марта 2013

IMO - у вас есть сериализованный список сегментов, и вы хотите объединить их.

Это до тех пор, пока последовательный порядок сегментов сохраняется через конкатенацию.

Процесс, запускаемый для каждой записи сегмента, чтобы ее можно было объединить ....

getVideoRaw to its own file
getAudioRaw to its own file

Когда вы разделились на сырье, все ваши сегменты делают это ...

concatenate video preserving serialized order so video segments remain correct order in videoConCatOUT.

concatenate the audio as above

затем объединяет соответствующие файлы concatOUT в один контейнер.

Это может быть записано в сценарии и может следовать стандарту. пример в ffmpeg FAQ по Concat

см. Раздел «3.14.4» здесь

Обратите внимание на команду 'tail' и объяснение о том, что строка отбрасывания отсутствует. 1 из всех, кроме первого сегмента, входящего в процесс concat ...

1 голос
/ 12 августа 2013

есть мультиплексор сегментатора https://ffmpeg.org/ffmpeg-formats.html#segment_002c-stream_005fsegment_002c-ssegment, который может помочь вам с тем, что вы ищете ...

1 голос
/ 11 мая 2012

Вы должны транскодировать перед сегментацией. Когда вы транскодируете отдельный сегмент, он каждый раз создает новый поток ts, а данные времени ts не копируются.

1 голос
/ 10 мая 2012

Посмотрите на фильтр setpts. Это должно дать вам достаточный контроль над PTS каждого куска.

...