Saltar al contenido

¿Cómo puedo usar ffmpeg para dividir videos MPEG en partes de 10 minutos?

Posterior a mirar en diversos repositorios y sitios de internet al final hemos descubierto la solución que te enseñamos ahora.

Solución:

$ 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
...

Envolver esto en un script para hacerlo en un bucle no sería difícil.

Tenga en cuenta que si intenta calcular el número de iteraciones en función de la salida de duración de un ffprobe llama que esto es estimado a partir de la tasa de bits promedio al comienzo del clip y el tamaño del archivo del clip, a menos que le -count_frames argumento, lo que ralentiza considerablemente su funcionamiento.

Otra cosa a tener en cuenta es que la posición del -ss La opción en la línea de comando es importante. Donde lo tengo ahora es lento pero preciso. La primera versión de esta respuesta dio la alternativa rápida pero inexacta. El artículo vinculado también describe una alternativa en su mayoría rápida pero aún precisa, por la que paga con un poco de complejidad.

Dejando todo eso a un lado, no creo que realmente quieras cortar exactamente 10 minutos por cada clip. Eso pondrá cortes justo en el medio de las oraciones, incluso las palabras. Creo que debería usar un editor o reproductor de video para encontrar puntos de corte naturales con una diferencia de menos de 10 minutos.

Suponiendo que su archivo está en un formato que YouTube puede aceptar directamente, no tiene que volver a codificar para obtener segmentos. Simplemente pase las compensaciones del punto de corte natural a ffmpeg, diciéndole que pase el A / V codificado sin tocar mediante el códec “copiar”:

$ 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
...

El -c copy El argumento le dice que copie todos los flujos de entrada (audio, video y potencialmente otros, como subtítulos) en la salida tal cual. Para programas A / V simples, es equivalente a los indicadores más detallados. -c:v copy -c:a copy o las banderas a la antigua -vcodec copy -acodec copy. Utilizaría el estilo más detallado cuando desee copiar solo una de las secuencias, pero volver a codificar la otra. Por ejemplo, hace muchos años existía una práctica común con los archivos QuickTime de comprimir el video con video H.264 pero dejar el audio como PCM sin comprimir; Si se encuentra con un archivo de este tipo hoy, puede modernizarlo con -c:v copy -c:a aac para reprocesar solo el flujo de audio, dejando el video intacto.

El punto de inicio para cada comando anterior después del primero es el punto de inicio del comando anterior más la duración del comando anterior.

Aquí está la solución de una línea:

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

Tenga en cuenta que esto no le brinda divisiones precisas, pero debe ajustarse a sus necesidades. En su lugar, cortará en el primer fotograma después del tiempo especificado después segment_time, en el código anterior sería después de la marca de 20 minutos.

Si encuentra que solo se puede reproducir el primer fragmento, intente agregar -reset_timestamps 1 como se menciona en los comentarios.

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

Enfrenté el mismo problema antes y armé un script de Python simple para hacer precisamente eso (usando FFMpeg). Disponible aquí: https://github.com/c0decracker/video-splitter y pegado a continuación:

#!/usr/bin/env python
import subprocess
import re
import math
from optparse import OptionParser
length_regexp = 'Duration: (d2):(d2):(d2).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)

valoraciones y reseñas

Si te gusta la invitación, tienes la opción de dejar un tutorial acerca de qué le añadirías a este enunciado.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *