Как я могу использовать ffmpeg для разделения видео MPEG на 10-минутные блоки?

Это прибывает к нам от BSD. Это поддается проверке. Но где это начиналось?

Вот объяснение неподдающееся проверке - BSD получил его от TOPS-20 O/S.

http://lists.freebsd.org/pipermail/freebsd-chat/2003-December/001725.html

70
21.11.2014, 03:05
10 ответов
$ ffmpeg -i source-file.foo -ss 0 -t 600 first-10-min.m4v
$ ffmpeg -i source-file.foo -ss 600 -t 600 second-10-min.m4v
$ ffmpeg -i source-file.foo -ss 1200 -t 600 third-10-min.m4v
...

При оборачивании этого в сценарий, чтобы сделать это в цикле не было бы твердо.

Остерегайтесь этого, при попытке вычислить количество повторений на основе вывода продолжительности от ffprobe назовите это, это оценивается от средней скорости передачи данных в начале клипа и размера файла клипа, если Вы не даете -count_frames аргумент, который значительно замедляет его операцию.

Другая вещь знать состоит в том что положение -ss опция по вопросам командной строки. Где у меня есть он, теперь является медленным, но точным. Первая версия этого ответа дала быструю, но неточную альтернативу. Связанная статья также описывает mostly-fast-but-still-accurate альтернативу, за которую Вы платите с небольшим количеством сложности.

Все, что в стороне, я не думаю Вы действительно, хочет сократить точно в 10 минут для каждого клипа. Это поместит сокращения прямо в середине предложений, даже слова. Я думаю, что необходимо использовать видео редактора или игрока для нахождения естественных точек разделения просто застенчивыми из на расстоянии в 10 минут.

Принятие Вашего файла находится в формате, который YouTube может принять непосредственно, Вы не должны повторно кодировать для получения сегментов. Просто передайте естественные смещения точки разделения ffmpeg, сообщение этого передать закодированный A/V через нетронутый при помощи кодека "копии":

$ ffmpeg -i source.m4v -ss 0 -t 593.3 -c copy part1.m4v
$ ffmpeg -i source.m4v -ss 593.3 -t 551.64 -c copy part2.m4v
$ ffmpeg -i source.m4v -ss 1144.94 -t 581.25 -c copy part3.m4v
...

-c copy аргумент говорит этому копировать все входные потоки (аудио, видео и потенциально другие, такие как подзаголовки) в вывод как есть. Для простых программ A/V это эквивалентно более подробным флагам -c:v copy -c:a copy или флаги старого стиля -vcodec copy -acodec copy. Вы использовали бы более подробный стиль, когда Вы хотите скопировать только один из потоков, но повторно закодировать другой. Например, много лет назад была обычная практика с файлами QuickTime, чтобы сжать видео с видео H.264, но оставить аудио, как несжатый PCM; если бы Вы натыкались на такой файл сегодня, то Вы могли бы модернизировать его с -c:v copy -c:a aac повторно обрабатывать просто аудиопоток, оставляя видео нетронутым.

Стартовая точка для каждой команды выше после первого является стартовой точкой предыдущей команды плюс продолжительность предыдущей команды.

72
27.01.2020, 19:31
  • 1
    пакетом, "сокращающее точно в 10 минут для каждого клипа", является положительной стороной. –  Chris 07.09.2010, 14:42
  • 2
    , возможно, при помощи-show_packets параметрического усилителя можно сделать это более точным. –  rogerdpack 14.06.2011, 00:36
  • 3
    , как поместить выше в цикл? –  kRazzy R 06.12.2017, 21:32
  • 4
    я Использование, которое этот cmd ya это разделил на право, но Теперь видео и аудио не находятся на СИНХРОНИЗАЦИИ никакая справка –  Sunil Chaudhary 16.03.2018, 08:08
  • 5
    @SunilChaudhary: форматы файлов A/V сложны, и не все программное обеспечение реализует их тот же путь, так, чтобы информация ffmpeg потребности поддержать синхронизацию между аудио-и видеопотоками не могли бы присутствовать в исходном файле. Если это происходит с Вами, существуют более сложные методы разделения, которые избегают проблемы. –  Warren Young 16.03.2018, 23:32

Обратите внимание, что точная пунктуация альтернативного формата -ss mm:ss.xxx. Я боролся в течение многих часов, пытаясь использовать интуитивное-но-неправильное mm:ss:xx напрасно.

$ man ffmpeg | grep -C1 position

- положение ss
Ищите на данное положение времени в секундах. "hh:mm:ss [.xxx]" синтаксис также поддерживается.

Ссылки здесь и здесь.

3
27.01.2020, 19:31

Ранее столкнулся с той же проблемой и собрал простой Python-скрипт, чтобы сделать именно это (используя FFMpeg). Доступно здесь: https://github.com/c0decracker/video-splitter, and pasted below:

#!/usr/bin/env python
import subprocess
import re
import math
from optparse import OptionParser
length_regexp = 'Duration: (\d{2}):(\d{2}):(\d{2})\.\d+,'
re_length = re.compile(length_regexp)
def main():
    (filename, split_length) = parse_options()
    if split_length <= 0:
        print "Split length can't be 0"
        raise SystemExit
    output = subprocess.Popen("ffmpeg -i '"+filename+"' 2>&1 | grep 'Duration'",
                              shell = True,
                              stdout = subprocess.PIPE
    ).stdout.read()
    print output
    matches = re_length.search(output)
    if matches:
        video_length = int(matches.group(1)) * 3600 + \
                       int(matches.group(2)) * 60 + \
                       int(matches.group(3))
        print "Video length in seconds: "+str(video_length)
    else:
        print "Can't determine video length."
        raise SystemExit
    split_count = int(math.ceil(video_length/float(split_length)))
    if(split_count == 1):
        print "Video length is less then the target split length."
        raise SystemExit
    split_cmd = "ffmpeg -i '"+filename+"' -vcodec copy "
    for n in range(0, split_count):
        split_str = ""
        if n == 0:
            split_start = 0
        else:
            split_start = split_length * n
            split_str += " -ss "+str(split_start)+" -t "+str(split_length) + \
                         " '"+filename[:-4] + "-" + str(n) + "." + filename[-3:] + \
                         "'"
    print "About to run: "+split_cmd+split_str
    output = subprocess.Popen(split_cmd+split_str, shell = True, stdout =
                              subprocess.PIPE).stdout.read()
def parse_options():
    parser = OptionParser()
    parser.add_option("-f", "--file",
                      dest = "filename",
                      help = "file to split, for example sample.avi",
                      type = "string",
                      action = "store"
    )
    parser.add_option("-s", "--split-size",
                      dest = "split_size",
                      help = "split or chunk size in seconds, for example 10",
                      type = "int",
                      action = "store"
    )
    (options, args) = parser.parse_args()
    if options.filename and options.split_size:
        return (options.filename, options.split_size)
    else:
        parser.print_help()
        raise SystemExit
if __name__ == '__main__':
    try:
        main()
    except Exception, e:
        print "Exception occured running main():"
        print str(e)
6
27.01.2020, 19:31

Вот однострочное решение :

ffmpeg -i input.mp4 -c copy -map 0 -segment_time 00:20:00 -f segment output%03d.mp4

Обратите внимание, что это не дает вам точного разделения, но должно соответствовать вашим потребностям. Вместо этого он будет вырезать первый кадр после времени, указанного после segment_time , в приведенном выше коде это будет после 20-минутной отметки.

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

ffmpeg -i input.mp4 -c copy -map 0 -segment_time 00:20:00 -f segment -reset_timestamps 1 output%03d.mp4
60
27.01.2020, 19:31

Просто используйте то, что встроено в ffmpeg, чтобы сделать именно это.

ffmpeg -i invid.mp4 -threads 3 -vcodec copy -f segment -segment_time 2 cam_out_h264%04d.mp4

Это разделит его примерно на 2-секундные фрагменты, разделит на соответствующие ключевые кадры и выведет в файлы cam_out_h2640001.mp4, cam_out_h2640002.mp4 и т. Д.

0
27.01.2020, 19:31

Если вы хотите создать действительно одинаковые фрагменты, вы должны заставить ffmpeg создавать -i-й кадр в первом кадре каждого фрагмента, чтобы вы могли использовать эту команду для создания 0,5-секундного фрагмента.

ffmpeg -hide_banner  -err_detect ignore_err -i input.mp4 -r 24 -codec:v libx264  -vsync 1  -codec:a aac  -ac 2  -ar 48k  -f segment   -preset fast  -segment_format mpegts  -segment_time 0.5 -force_key_frames  "expr: gte(t, n_forced * 0.5)" out%d.mkv
9
27.01.2020, 19:31
#!/bin/bash

if [ "X$1" == "X" ]; then
    echo "No file name for split, exiting..."
    exit 1
fi

if [ ! -f "$1" ]; then
    echo "The file '$1' doesn't exist. exiting..."
    exit 1
fi

duration=$(ffmpeg -i "$1" 2>&1 | grep Duration | sed 's/^.*Duration: \(.*\)\..., start.*$/\1/' | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')      #'
split_time=${split_time:-55}
time=0
part=1

filename=${file%%.*}
postfix=${file##*.}

while [ ${time} -le ${duration} ]; do

echo    ffmpeg -i "$1" -vcodec copy -ss ${time} -t ${split_time} "${filename}-${part}.${postfix}"
    (( part++ ))
    (( time = time + split_time ))

done
-1
27.01.2020, 19:31

Альтернативным более читаемым способом будет

ffmpeg -i input.mp4 -ss 00:00:00 -to 00:10:00 -c copy output1.mp4
ffmpeg -i input.mp4 -ss 00:10:00 -to 00:20:00 -c copy output2.mp4

/**
* -i  input file
* -ss start time in seconds or in hh:mm:ss
* -to end time in seconds or in hh:mm:ss
* -c codec to use
*/

Вотисточник и список часто используемых команд FFmpeg.

11
27.01.2020, 19:31

Однострочное решение


for i in {3..100}; do ffmpeg -i input.mp4 -ss $(($((i))*600)) -t $(($((i+1))*600)) $i.mp4 ; done;

-1
24.09.2020, 06:58

Пожалуйста, ознакомьтесь с приведенной ниже командой

fun trim(): Array<String?>{
        val cmdList = ArrayList<String>()
        var cmds: Array<String?>? = null
        try{
            cmdList.add("-y")

            cmdList.add("-ss")
            cmdList.add(startduration.toString())
            cmdList.add("-t")
            cmdList.add(endduration.toString())
            cmdList.add("-i")
            cmdList.add(sourcevideopath)
            cmdList.add("-vcodec")
            cmdList.add("copy")

            cmdList.add("-movflags")
            cmdList.add("faststart")
            cmdList.add("-preset")
            cmdList.add("ultrafast")

            cmdList.add(outputvideopath)

            cmds = arrayOfNulls<String>(cmdList.size)
            cmdList.toArray(cmds)

        }catch (e:Exception){
            e.printStackTrace()
        }
        return cmds!!
    }
-1
23.06.2021, 09:43

Теги

Похожие вопросы