usar tutorial mac jdownloader how gui descargar como actualizar ffmpeg

tutorial - ¿Hay una manera elegante de dividir un archivo por capítulo usando ffmpeg?



ffmpeg tutorial (5)

(Edición: este consejo provino de https://github.com/phiresky través de este problema: https://github.com/harryjackson/ffmpeg_split/issues/2 )

Puedes obtener capítulos usando:

ffprobe -i fname -print_format json -show_chapters -loglevel error

Si volviera a escribir esto, usaría las opciones json de ffprobe

(La respuesta original sigue)

Este es un script de python de trabajo. Lo probé en varios videos y funcionó bien. Python no es mi primer idioma, pero noté que lo usas, así que creo que escribirlo en Python podría tener más sentido. Lo he añadido a Github . Si desea mejorar por favor envíe solicitudes de extracción.

#!/usr/bin/env python import os import re import subprocess as sp from subprocess import * from optparse import OptionParser def parseChapters(filename): chapters = [] command = [ "ffmpeg", ''-i'', filename] output = "" try: # ffmpeg requires an output file and so it errors # when it does not get one so we need to capture stderr, # not stdout. output = sp.check_output(command, stderr=sp.STDOUT, universal_newlines=True) except CalledProcessError, e: output = e.output for line in iter(output.splitlines()): m = re.match(r".*Chapter #(/d+:/d+): start (/d+/./d+), end (/d+/./d+).*", line) num = 0 if m != None: chapters.append({ "name": m.group(1), "start": m.group(2), "end": m.group(3)}) num += 1 return chapters def getChapters(): parser = OptionParser(usage="usage: %prog [options] filename", version="%prog 1.0") parser.add_option("-f", "--file",dest="infile", help="Input File", metavar="FILE") (options, args) = parser.parse_args() if not options.infile: parser.error(''Filename required'') chapters = parseChapters(options.infile) fbase, fext = os.path.splitext(options.infile) for chap in chapters: print "start:" + chap[''start''] chap[''outfile''] = fbase + "-ch-"+ chap[''name''] + fext chap[''origfile''] = options.infile print chap[''outfile''] return chapters def convertChapters(chapters): for chap in chapters: print "start:" + chap[''start''] print chap command = [ "ffmpeg", ''-i'', chap[''origfile''], ''-vcodec'', ''copy'', ''-acodec'', ''copy'', ''-ss'', chap[''start''], ''-to'', chap[''end''], chap[''outfile'']] output = "" try: # ffmpeg requires an output file and so it errors # when it does not get one output = sp.check_output(command, stderr=sp.STDOUT, universal_newlines=True) except CalledProcessError, e: output = e.output raise RuntimeError("command ''{}'' return with error (code {}): {}".format(e.cmd, e.returncode, e.output)) if __name__ == ''__main__'': chapters = getChapters() convertChapters(chapters)

En esta página , Albert Armea comparte un código para dividir videos por capítulo usando ffmpeg . El código es sencillo, pero no bastante atractivo.

ffmpeg -i "$ FUENTE. $ EXT" 2> & 1 | Capítulo grep | sed -E "s / * Capítulo # ([0-9] +. [0-9] +): inicio ([0-9] +. [0-9] +), final ([0-9] + . [0-9] +) / - i / "$ SOURCE. $ EXT /" -copia de vcodec -codecec -ss / 2 -to / 3 / "$ SOURCE- / 1. $ EXT /" / "| xargs -n 11 ffmpeg

¿Hay una manera elegante de hacer este trabajo?


Modifiqué el script de Harry para usar el nombre del capítulo para el nombre del archivo. Da salida a un nuevo directorio con el nombre del archivo de entrada (extensión menos). También prefija el nombre de cada capítulo con "1 -", "2 -", etc. en caso de que haya capítulos con el mismo nombre.

#!/usr/bin/env python import os import re import pprint import sys import subprocess as sp from os.path import basename from subprocess import * from optparse import OptionParser def parseChapters(filename): chapters = [] command = [ "ffmpeg", ''-i'', filename] output = "" m = None title = None chapter_match = None try: # ffmpeg requires an output file and so it errors # when it does not get one so we need to capture stderr, # not stdout. output = sp.check_output(command, stderr=sp.STDOUT, universal_newlines=True) except CalledProcessError, e: output = e.output num = 1 for line in iter(output.splitlines()): x = re.match(r".*title.*: (.*)", line) print "x:" pprint.pprint(x) print "title:" pprint.pprint(title) if x == None: m1 = re.match(r".*Chapter #(/d+:/d+): start (/d+/./d+), end (/d+/./d+).*", line) title = None else: title = x.group(1) if m1 != None: chapter_match = m1 print "chapter_match:" pprint.pprint(chapter_match) if title != None and chapter_match != None: m = chapter_match pprint.pprint(title) else: m = None if m != None: chapters.append({ "name": `num` + " - " + title, "start": m.group(2), "end": m.group(3)}) num += 1 return chapters def getChapters(): parser = OptionParser(usage="usage: %prog [options] filename", version="%prog 1.0") parser.add_option("-f", "--file",dest="infile", help="Input File", metavar="FILE") (options, args) = parser.parse_args() if not options.infile: parser.error(''Filename required'') chapters = parseChapters(options.infile) fbase, fext = os.path.splitext(options.infile) path, file = os.path.split(options.infile) newdir, fext = os.path.splitext( basename(options.infile) ) os.mkdir(path + "/" + newdir) for chap in chapters: chap[''name''] = chap[''name''].replace(''/'','':'') chap[''name''] = chap[''name''].replace("''","/'") print "start:" + chap[''start''] chap[''outfile''] = path + "/" + newdir + "/" + re.sub("[^-a-zA-Z0-9_.():'' ]+", '''', chap[''name'']) + fext chap[''origfile''] = options.infile print chap[''outfile''] return chapters def convertChapters(chapters): for chap in chapters: print "start:" + chap[''start''] print chap command = [ "ffmpeg", ''-i'', chap[''origfile''], ''-vcodec'', ''copy'', ''-acodec'', ''copy'', ''-ss'', chap[''start''], ''-to'', chap[''end''], chap[''outfile'']] output = "" try: # ffmpeg requires an output file and so it errors # when it does not get one output = sp.check_output(command, stderr=sp.STDOUT, universal_newlines=True) except CalledProcessError, e: output = e.output raise RuntimeError("command ''{}'' return with error (code {}): {}".format(e.cmd, e.returncode, e.output)) if __name__ == ''__main__'': chapters = getChapters() convertChapters(chapters)

Esto tomó un poco de tiempo, ya que definitivamente no soy un tipo de Python. También es poco elegante, ya que había muchos obstáculos para saltar, ya que está procesando los metadatos línea por línea. (Es decir, los datos de título y capítulo se encuentran en bucles separados a través de la salida de metadatos)

Pero funciona y debería ahorrarle mucho tiempo. ¡Lo hizo por mí!


Quería algunas cosas extra como:

  • extrayendo la tapa
  • usando el nombre del capítulo como nombre de archivo
  • prefijando un contador al nombre de archivo con ceros iniciales, para que el orden alfabético funcione correctamente en cada software
  • haciendo una lista de reproducción
  • Modificar los metadatos para incluir el nombre del capítulo.
  • salida de todos los archivos a un nuevo directorio basado en metadatos (año autor - título)

Aquí está mi script (utilicé la sugerencia con la salida de ffprobe json de Harry)

#!/bin/bash input="input.aax" EXT2="m4a" json=$(ffprobe -activation_bytes secret -i "$input" -loglevel error -print_format json -show_format -show_chapters) title=$(echo $json | jq -r ".format.tags.title") count=$(echo $json | jq ".chapters | length") target=$(echo $json | jq -r ".format.tags | .date + /" /" + .artist + /" - /" + .title") mkdir "$target" ffmpeg -activation_bytes secret -i $input -vframes 1 -f image2 "$target/cover.jpg" echo "[playlist] NumberOfEntries=$count" > "$target/0_Playlist.pls" for i in $(seq -w 1 $count); do j=$((10#$i)) n=$(($j-1)) start=$(echo $json | jq -r ".chapters[$n].start_time") end=$(echo $json | jq -r ".chapters[$n].end_time") name=$(echo $json | jq -r ".chapters[$n].tags.title") ffmpeg -activation_bytes secret -i $input -vn -acodec -map_chapters -1 copy -ss $start -to $end -metadata title="$title $name" "$target/$i $name.$EXT2" echo "File$j=$i $name.$EXT2" >> "$target/0_Playlist.pls" done


Una versión del código de shell original con

  • mejora la eficiencia utilizando ffprobe lugar de ffmpeg ,
  • expresión regular simplificada,
  • Fiabilidad mejorada al evitar xargs y
  • Mejor legibilidad mediante el uso de múltiples líneas.

En mi versión 4.1 de ffprobe , los números de los capítulos están separados por : cuales deben ser reemplazados por . para evitar que ffmpeg queje de un Protocol not found .

ffprobe "$INPUT" 2>&1 | sed -En ''s/.*Chapter #([0-9]+)[.:]([0-9]+): start ([0-9]+/.[0-9]+), end ([0-9]+/.[0-9]+).*//1./2 /3 /4/p'' | while read chapter start end do ffmpeg </dev/null / -i "$INPUT" / -vcodec copy -acodec copy / -ss "$start" -to "$end" / "${INPUT%.*}-$chapter.${INPUT##*.}" done

La entrada de ffmpeg se redirige para evitar que interfiera con el bucle.


ffmpeg -i "$SOURCE.$EXT" 2>&1 / # get metadata about file | grep Chapter / # search for Chapter in metadata and pass the results | sed -E "s/ *Chapter #([0-9]+.[0-9]+): start ([0-9]+.[0-9]+), end ([0-9]+.[0-9]+)/-i /"$SOURCE.$EXT/" -vcodec copy -acodec copy -ss /2 -to /3 /"$SOURCE-/1.$EXT/"/" / # filter the results, explicitly defining the timecode markers for each chapter | xargs -n 11 ffmpeg # construct argument list with maximum of 11 arguments and execute ffmpeg

Su comando analiza los metadatos de los archivos y lee los marcadores de código de tiempo de cada capítulo. Podrías hacer esto manualmente para cada capítulo.

ffmpeg -i ORIGINALFILE.mp4 -acodec copy -vcodec copy -ss 0 -t 00:15:00 OUTFILE-1.mp4

o puede escribir los marcadores de capítulo y ejecutarlos con este script bash que es un poco más fácil de leer.

#!/bin/bash # Author: http://crunchbang.org/forums/viewtopic.php?id=38748#p414992 # m4bronto # Chapter #0:0: start 0.000000, end 1290.013333 # first _ _ start _ end while [ $# -gt 0 ]; do ffmpeg -i "$1" 2> tmp.txt while read -r first _ _ start _ end; do if [[ $first = Chapter ]]; then read # discard line with Metadata: read _ _ chapter ffmpeg -vsync 2 -i "$1" -ss "${start%?}" -to "$end" -vn -ar 44100 -ac 2 -ab 128 -f mp3 "$chapter.mp3" </dev/null fi done <tmp.txt rm tmp.txt shift done

o puede usar HandbrakeCLI, como se mencionó originalmente en esta publicación , este ejemplo extrae el capítulo 3 a 3.mkv

HandBrakeCLI -c 3 -i originalfile.mkv -o 3.mkv

u otra herramienta se menciona en este post

mkvmerge -o output.mkv --split chapters:all input.mkv