En tant que tendance récente des lecteurs de musique, il existe une tendance selon laquelle les gens ne peuvent pas se rassembler au même endroit et jouer ensemble, ils prennent donc une vidéo pour chacun et la modifient plus tard pour en faire une vidéo et la publier. Je n'ai pas beaucoup de connaissances en musique et en gros je ne la joue pas moi-même. Cependant, il y a des gens impliqués dans la musique autour de moi, et on me demande souvent de monter des vidéos. Pour soutenir cela, j'ai utilisé Ruby pour exécuter ffmpeg et créé un environnement dans lequel le montage vidéo peut être effectué de manière semi-automatique.
Désormais, même les personnes sans connaissances peuvent facilement filmer des vidéos de performance à l'aide de smartphones. … Mais cela signifie également que tout le monde envoie des vidéos dans différents formats, tailles vidéo et fréquences d'images. Je pense qu'il existe un meilleur moyen d'éviter la détérioration de la vidéo, mais elle est traitée par une méthode étape par étape comme suit.
Puisqu'il est supposé s'exécuter dans un environnement Windows, ceux qui y font référence doivent faire attention à l'utilisation du caractère .
movie_on_playing.rb
control_file = ARGV[0]
cfile = File.open(control_file, "r")
def system_log( exe, workd )
fho = File.open("#{workd}\\log.txt", "a")
fho.write("#{exe}\n")
fho.close
res = system( exe )
unless(res)
puts "# Error! ffmpeg failed. See #{workd}\\log.txt to confirm command."
exit
end
end
out_width = 0
out_height = 0
movie = []
resize = []
volume = []
fadein = []
delay = []
delay_f = []
to_time = []
blackf = []
crop_xy = []
crop_size = []
skip = []
row_div = []
row_flag = true
ri = 0
for s1 in cfile
next if s1 =~ /^#/
a1 = s1.chomp.split(" ")
if(a1[0] == "ffmpeg")
ffmpeg = a1[1]
next
end
if(a1[0] == "work")
workd = a1[1]
next
end
if(a1[0] == "out")
out_file_name = a1[1]
system("title #{out_file_name}")
next
end
if(a1[0] == "movie")
movie << a1[1]
next
end
if(a1[0] == "resize")
resize << a1[1]
next
end
if(a1[0] == "volume")
volume << a1[1]
next
end
if(a1[0] == "fadein")
fadein << a1[1]
next
end
if(a1[0] == "delay")
delay << a1[1]
delay_f << a1[2] if(a1[1].to_f > 0)
next
end
if(a1[0] == "time")
to_time << a1[1]
next
end
if(a1[0] == "crop")
crop_xy << a1[1]
crop_size << a1[2]
if(row_div.size == 0)
out_width = out_width + a1[2].split("x")[0].to_i
end
if row_flag
out_height = out_height + a1[2].split("x")[1].to_i
row_flag = false
end
next
end
if(a1[0] == "skip")
skip << a1[1]
next
end
if(a1[0] == "row_div")
row_div << movie.size
row_flag = true
next
end
end
cfile.close
Dir.mkdir(workd) unless File.exist?(workd)
efile_mp4 = []
efile_mp3 = []
ovl_vx = 0
ovl_vy = 0
ovl_a = []
fho = File.open("#{workd}\\log.txt", "a")
fho.write("\n#{Time.now}\n")
fho.close
out_width_e = out_width
out_height_e = out_height
fi = 0
w_reset = false
row_div << 9999
for i in 0...movie.size
filen = movie[i].split("\\")[-1].split(".")[0]
filee = movie[i].split("\\")[-1].split(".")[1]
file_rsz = "#{filen}_#{resize[i]}"
rx = resize[i].split("x")[0]
ry = resize[i].split("x")[1]
####################
#### resize part ###
####################
if(delay[i].to_f > 0.0)
fade_time = 0
else
fade_time = -1 * delay[i].to_f
end
if(delay[i].to_f > 0)
if(fadein[i].to_i > 0)
fade_in = "fade=in:0:#{fadein[i]},"
else
fade_in = ""
end
system_log( "#{ffmpeg} -y -i \"#{movie[i]}\" -vf \"#{fade_in}scale=#{rx}:#{ry}\" \"#{workd}\\#{file_rsz}.#{filee}\"", workd ) if(skip[i] == "off")
else
system_log( "#{ffmpeg} -y -i \"#{movie[i]}\" -vf \"scale=#{rx}:#{ry}\" \"#{workd}\\#{file_rsz}.#{filee}\"", workd ) if(skip[i] == "off")
end
######################
### black mov part ###
######################
if(delay[i].to_f > 0.0)
dname = delay[i].gsub(".","p")
bfile = "black_#{resize[i]}_#{dname}.#{filee}"
if(delay_f[fi] == nil)
frate = "30000/1001"
else
frate = delay_f[fi]
end
system_log( "#{ffmpeg} -y -f lavfi -i \"color=c=black:s=#{resize[i]}:r=#{frate}:d=#{delay[i]}\" -f lavfi -i \"aevalsrc=0|0:c=stereo:s=44100:d=#{delay[i]}\" \"#{workd}\\#{bfile}\"", workd ) if(skip[i] == "off")
blackf << bfile
fi = fi + 1
else
blackf << "black_0"
end
#######################
### concat/cut part ###
#######################
if(blackf[i] != "black_0")
# add plus delay
con_filen = "#{workd}\\concat_#{i}.txt"
con_file = File.open(con_filen, "w")
con_file.write("file #{workd}/#{blackf[i]}\n")
con_file.write("file #{workd}/#{file_rsz}.#{filee}\n")
con_file.close
file_cn = "#{file_rsz}_con"
system_log( "#{ffmpeg} -y -safe 0 -f concat -i \"#{con_filen}\" -c:v copy -c:a copy -map 0:v -map 0:a \"#{workd}\\#{file_cn}.#{filee}\"", workd ) if(skip[i] == "off")
elsif(delay[i].to_f < 0)
# add minus delay
cut_time = -1 * delay[i].to_f
file_ct = "#{filen}_cut"
system_log( "#{ffmpeg} -y -i \"#{workd}\\#{file_rsz}.#{filee}\" -ss #{cut_time} \"#{workd}\\#{file_ct}.#{filee}\"", workd ) if(skip[i] == "off")
file_cn = file_ct
else
# not add delay
file_cn = file_rsz
end
###########################
### fade, crop, to part ###
###########################
crop_x = crop_xy[i].split("x")[0]
crop_y = crop_xy[i].split("x")[1]
crop_w = crop_size[i].split("x")[0]
crop_h = crop_size[i].split("x")[1]
cropt = "crop=#{crop_w}:#{crop_h}:#{crop_x}:#{crop_y}"
if(w_reset)
out_width_e = out_width
out_height_e = out_height_e - crop_h.to_i
w_reset = false
end
if( out_width_e - crop_w.to_i > 0 || out_height_e - crop_h.to_i > 0)
padt = ",pad=#{out_width_e}:#{out_height_e}:0:0"
else
padt = ""
end
if(to_time[i].to_f > 0)
tot = "-to #{to_time[i].to_f + delay[i].to_f}"
else
tot = ""
end
file_crp = "#{file_rsz}_cropped"
if(delay[i].to_f > 0)
system_log( "#{ffmpeg} -y -i \"#{workd}\\#{file_cn}.#{filee}\" -vf \"#{cropt}#{padt}\" #{tot} \"#{workd}\\#{file_crp}.#{filee}\"", workd ) if(skip[i] == "off")
else
if(fadein[i].to_i > 0)
fade_in = "fade=in:0:#{fadein[i]},"
else
fade_in = ""
end
system_log( "#{ffmpeg} -y -i \"#{workd}\\#{file_cn}.#{filee}\" -vf \"#{fade_in}#{cropt}#{padt}\" #{tot} \"#{workd}\\#{file_crp}.#{filee}\"", workd ) if(skip[i] == "off")
end
out_width_e = out_width_e - crop_w.to_i
if(row_div.size > 0)
if(i == row_div[ri] - 1)
ovl_vx = 0
ovl_vy = ovl_vy + crop_h.to_i
ri = ri + 1
w_reset = true
else
ovl_vx = ovl_vx + crop_w.to_i
end
else
ovl_vx = ovl_vx + crop_w.to_i
end
ovl_a << [ovl_vx, ovl_vy]
############################
### mp3 out, volume part ###
############################
vol_e = volume[i].to_f / 100
system_log( "#{ffmpeg} -y -i \"#{workd}\\#{file_crp}.#{filee}\" -vn -acodec libmp3lame -ar 44100 -ab 256k -af \"volume=#{vol_e}\" \"#{workd}\\#{filen}.mp3\"", workd ) if(skip[i] == "off")
efile_mp3 << "#{workd}\\#{filen}.mp3"
efile_mp4 << "#{workd}\\#{file_crp}.#{filee}"
end
####################
### overlay part ###
####################
in_file = ""
for efile in efile_mp4
in_file = "#{in_file} -i \"#{efile}\""
end
ovlt = ""
for i in 0...ovl_a.size - 1
if(ovlt == "")
ovlt = "overlay=x=#{ovl_a[i][0]}:y=#{ovl_a[i][1]}"
else
ovlt = "#{ovlt},overlay=x=#{ovl_a[i][0]}:y=#{ovl_a[i][1]}"
end
end
system_log( "#{ffmpeg} -y#{in_file} -filter_complex \"#{ovlt}\" -an \"#{workd}\\out_movie.#{filee}\"", workd )
######################
### add audio part ###
######################
in_file = ""
for efile in efile_mp3
in_file = "#{in_file} -i \"#{efile}\""
end
system_log( "#{ffmpeg} -y -i \"#{workd}\\out_movie.#{filee}\" #{in_file} -filter_complex \"amix=inputs=#{efile_mp3.size}:duration=longest:dropout_transition=2\" \"#{out_file_name}\"", workd )
3.1 Control file Un fichier de contrôle a été créé et lu pour spécifier l'emplacement du fichier vidéo et la méthode d'édition. Ce qui suit est un exemple. De plus, la vidéo après avoir entré le mot-clé "row_div" sera connectée verticalement au lieu d'horizontal.
control.txt
ffmpeg C:\ffmpeg\bin\ffmpeg.exe
work work
out out.mp4
movie org_data\a-san.mp4
resize 1280x720
volume 100
fadein 60
delay 1.5
time 208.5
crop 0x0 640x720
skip off
movie org_data\b-san.mp4
resize 1280x720
volume 120
fadein 60
delay -2.5
time 212.5
crop 320x0 640x720
skip off
ruby movie_on_playing.rb control.txt
Avec des commandes telles que, les commandes ffmpeg sont générées et exécutées séquentiellement en fonction des informations de contrôle.
Le traitement de chaque partie est expliqué selon la partie ○○ de la section commentaire.
4.1. Resize part Redimensionnez la vidéo en fonction du paramètre "redimensionner" dans le fichier de contrôle. Mettez la valeur de redimensionnement après "scale =" et générez la commande suivante.
ffmpeg.exe -y -i "org_data\a-san.mp4" -vf "scale=1280:720" "work\a-san_1280x720.mp4"
Si la valeur de "delay" est +, la vidéo qui n'affiche rien avant sera liée, donc le fondu sera également défini ici.
ffmpeg.exe -y -i "org_data\a-san.mp4" -vf "fade=in:0:30,scale=1280:720" "work\a-san_1280x720.mp4"
4.2. Black movie part Si la valeur de "delay" est + (pour retarder le début de la vidéo), une vidéo sans vidéo sera créée s'il n'y a pas de son pendant le nombre de secondes spécifié (Remarque: pas sans son). Mettez la valeur après "d =" et générez la commande suivante.
ffmpeg.exe -y -f lavfi -i "color=c=black:s=1280x720:r=30000/1001:d=1.5" -f lavfi -i "aevalsrc=0|0:c=stereo:s=44100:d=1.5" "work\black_1280x720_1p5.mp4"
Etant donné que ce processus a tendance à poser des problèmes dans la vidéo après la concaténation, l'image peut être modifiée dans la 3ème colonne avec "délai [secondes] [fréquence d'images]". Cependant, cette méthode peut ne pas fonctionner correctement, donc lors de l'édition d'une vidéo à l'aide de ffmpeg, il est plus facile de filmer avec une marge suffisante de la vidéo originale, puis de la couper. Si vous souhaitez tourner une vidéo à partir de maintenant, dites à l'interprète: "Appuyez sur le bouton d'enregistrement, attendez environ 5 secondes, puis lancez la lecture."
4.3. Concat/cut part Si la valeur de "delay" est- (pour démarrer la vidéo plus tôt), mettez-la dans la valeur de "-ss" et générez la commande suivante.
ffmpeg.exe -y -i "work\a-san_1280x720.mp4" -ss 2.5 "work\a-san_1280x720_cut.mp4"
Si la valeur de "délai" est +, il sera lié à la vidéo précédente sans vidéo.
ffmpeg.exe -y -safe 0 -f concat -i "work\concat_1.txt" -c:v copy -c:a copy -map 0:v -map 0:a "work\a-san_1280x720_con.mp4"
4.4. Fade, crop, to part Ici, vous pouvez recadrer la vidéo et spécifier l'heure de fin. Si la valeur de "delay" est-, réglez le fondu ici. Dans ffmpeg, la taille après recadrage et la position de recadrage sont spécifiées dans cet ordre, mais comme c'était un peu difficile à comprendre personnellement, le fichier de contrôle utilise le format "recadrage [position de recadrage] [taille après recadrage]". Il est converti en "crop (X1) x (Y1) (X2) x (Y2)" → ffmpeg "crop = (X2): (Y2): (X1): (Y1)". L'un des points forts de l'utilisation de Ruby est que vous pouvez décider vous-même du format en fonction de vos préférences.
La valeur de "pad =" est calculée à partir de la taille recadrée de chaque vidéo. "-to" est calculé à partir des valeurs de "time" et "delay" dans le fichier de contrôle.
ffmpeg.exe -y -i "work\a-san_1280x720_cut.mp4" -vf "fade=in:0:30,crop=640:720:0:0,pad=1280:720:0:0" -to 210.0 "work\a-san_1280x720_cropped.mp4"
4.5. Mp3 out, volume part Extrayez des fichiers sonores uniquement à partir de vidéos chronométrées (avec -ss et -to définis). Dans ffmpeg, 100% du volume est "1.0", mais dans le fichier de contrôle, 100% est "100". Mettez "valeur de réglage / 100" après "volume =" et générez la commande suivante.
ffmpeg.exe -y -i "work\a-san_1280x720_cropped.mp4" -vn -acodec libmp3lame -ar 44100 -ab 256k -af "volume=1.0" "work\a-san.mp3"
4.6. Overlay part Les vidéos ajustées individuellement sont combinées en une seule vidéo par superposition. Calculez à partir de la valeur de récolte et générez la commande suivante.
ffmpeg.exe -y -i "work\a-san_1280x720_cropped.mp4" -i "work\b-san_1280x720_cropped.mp4" -filter_complex "overlay=x=640:y=0" -an "work\out_movie.mp4"
4.7. Add audio part Enfin, entrez tous les sons et vous avez terminé. Conservez le nom du fichier mp3 comme un tableau, connectez-les dans l'ordre avec -i, entrez la taille du tableau comme valeur de "amix = inputs =" et générez la commande suivante.
ffmpeg.exe -y -i "work\out_movie.mp4" -i "work\a-san.mp3" -i "work\a-san.mp3" -filter_complex "amix=inputs=2:duration=longest:dropout_transition=2" "out.mp4"
Ce "out.mp4" est une vidéo terminée.
L'un des principaux inconvénients de la saisie de commandes dans CUI et de l'édition de vidéos est que vous ne pouvez pas éditer tout en regardant ou en écoutant la synchronisation et le volume. Par conséquent, la vidéo créée par la méthode ci-dessus est
Etc. peut être demandé. À ce stade, afin d'accélérer la ** vidéo non ajustée en utilisant le résultat précédent **, créez un élément appelé "ignorer" dans le fichier de contrôle, et s'il est "activé", ignorez le traitement de cette vidéo. Je le fais.
ffmpeg est un outil très sophistiqué et facile à utiliser que j'utilise depuis longtemps, mais c'est beaucoup de travail de taper des dizaines ou des centaines de commandes, notamment pour calculer et saisir des informations liées à la taille de la vidéo. Est requis. J'espère que cet article vous a aidé à faciliter cet effort.
Recommended Posts