Это прибывает к нам от BSD. Это поддается проверке. Но где это начиналось?
Вот объяснение неподдающееся проверке - BSD получил его от TOPS-20 O/S.
http://lists.freebsd.org/pipermail/freebsd-chat/2003-December/001725.html
$ 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
повторно обрабатывать просто аудиопоток, оставляя видео нетронутым.
Стартовая точка для каждой команды выше после первого является стартовой точкой предыдущей команды плюс продолжительность предыдущей команды.
Обратите внимание, что точная пунктуация альтернативного формата -ss mm:ss.xxx
. Я боролся в течение многих часов, пытаясь использовать интуитивное-но-неправильное mm:ss:xx
напрасно.
$ man ffmpeg | grep -C1 position
- положение ss
Ищите на данное положение времени в секундах. "hh:mm:ss [.xxx]" синтаксис также поддерживается.
Ранее столкнулся с той же проблемой и собрал простой 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)
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
Просто используйте то, что встроено в 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 и т. Д.
Если вы хотите создать действительно одинаковые фрагменты, вы должны заставить 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
#!/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
Альтернативным более читаемым способом будет
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.
Однострочное решение
for i in {3..100}; do ffmpeg -i input.mp4 -ss $(($((i))*600)) -t $(($((i+1))*600)) $i.mp4 ; done;
Пожалуйста, ознакомьтесь с приведенной ниже командой
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!!
}
ffmpeg
потребности поддержать синхронизацию между аудио-и видеопотоками не могли бы присутствовать в исходном файле. Если это происходит с Вами, существуют более сложные методы разделения, которые избегают проблемы. – Warren Young 16.03.2018, 23:32