contribution
Sortie (lorsque vous l'utilisez réellement, combinez les deux fichiers suivants avec ffmpeg ou un logiciel de montage vidéo)
cut_movie.py
import datetime
import os
import cv2
import librosa
import numpy as np
import scipy
#Une fonction à sortir sur la console d'une manière agréable. Il ne faut pas que cela passe comme ca.
def pretty_print_sec(sec):
int_sec = int(sec)
hour = int_sec // 3600
left_sec = int_sec - hour * 3600
minute = left_sec // 60
left_sec = left_sec - minute * 60
hour_str = ("00" + str(hour))[-2:]
min_str = ("00" + str(minute))[-2:]
sec_str = ("00" + str(left_sec))[-2:]
return ":".join([hour_str, min_str, sec_str])
#Fonction utilisée pour vérifier si le nombre cible de secondes est la cible de l'écrêtage
def is_in(tuple_list, val):
for tup in tuple_list:
if tup[0] <= val <= tup[1]:
return True
return False
#Utilisez ceci lors du recadrage basé sur la valeur maximale
def cut_by_max_rms(rms, percentile):
is_on = False
start = 0
end = 0
threshold = np.percentile(rms[0], percentile)
cut_list = []
#Si l'image précédente a également été sélectionnée pour le recadrage, combinez les plages de recadrage
for i, val in enumerate(rms[0]):
if val >= threshold and is_on:
pass
elif val >= threshold and not is_on:
is_on = True
start = float(i) * 30
elif val < threshold and is_on:
end = float(i) * 30
is_on = False
cut_list.append((start, end))
else:
pass
if is_on:
cut_list.append((start, float(i + 1) * 30))
return cut_list
#Utilisez ceci pour la base de points maximale
def cut_by_local_max_rms(rms, max_frame_num):
cut_list = []
order = 1
while True:
pts = list(scipy.signal.argrelmax(rms[0], order=order)[0])
if len(pts) < max_frame_num:
break
order += 1
for point in pts:
cut_list.append((point * 30, (point + 1) * 30))
return cut_list
#Identification de l'emplacement de la découpe
#Découpez en fonction du volume
def decide_cut_frames(cut_type, voice_file):
#Charger l'audio pour identifier les cultures
#Je veux le rendre aussi léger que possible, donc je le lis à une fréquence d'échantillonnage de 8000
y_voice, sr_voice = librosa.load(voice_file, sr=8000, mono=True)
#Vérifiez le volume toutes les 30 secondes
rms = librosa.feature.rms(
y=y_voice,
frame_length=sr_voice * 30,
hop_length=sr_voice * 30,
center=True,
pad_mode="reflect",
)
if cut_type == "local_max":
#Le volume est maximum(Où se trouve le sommet)Sélectionnez jusqu'à 20 images et découpez
cut_list = cut_by_local_max_rms(rms, 20)
elif cut_type == "max":
#Top 5 des plus bruyants%Découpez le cadre de
cut_list = cut_by_local_max_rms(rms, 100 - 95)
return cut_list
#Recadrage vidéo
def cut_movie(cut_list, movie_file, output_movie_file):
movie = cv2.VideoCapture(movie_file)
fps = movie.get(cv2.CAP_PROP_FPS)
height = movie.get(cv2.CAP_PROP_FRAME_HEIGHT)
width = movie.get(cv2.CAP_PROP_FRAME_WIDTH)
print(fps, int(width), int(height))
#Format à la sortie
#Notez que cela peut changer en fonction du système d'exploitation
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
#S'il existe déjà, une erreur se produira, supprimez-la donc une fois.
if os.path.exists(output_movie_file):
os.remove(output_movie_file)
out = cv2.VideoWriter(
output_movie_file, fourcc, int(fps), (int(width), int(height))
)
for start, end in cut_list:
i = start * fps
movie.set(0, start * 1000)
#Lecture image par image depuis le début et pause lorsque la fin est dépassée
while movie.isOpened():
sec = float(i / fps)
if sec % 60 == 0:
print(pretty_print_sec(sec), datetime.datetime.now(), flush=True)
ret, frame = movie.read()
if not ret:
break
#Ajouter du texte pour l'heure actuelle
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(
frame,
pretty_print_sec(sec),
(10, int(height * 0.9)),
font,
1,
(0, 255, 0),
2,
cv2.LINE_AA,
)
if is_in(cut_list, sec):
out.write(frame)
i += 1
if sec > end:
break
movie.release()
out.release()
#Recadrage audio
def cut_audio(cut_list, voice_file, output_audio_file):
#Notez que sr sera de 22050 si None est spécifié.
y_full, sr_full = librosa.load(voice_file, sr=None, mono=False)
output_array = [[], []]
for start, end in cut_list:
for i in range(int(start * sr_full), int(end * sr_full) + 1):
val_0 = y_full[0, i]
val_1 = y_full[1, i]
sec = float(i / sr_full)
if sec % 60 == 0:
print(pretty_print_sec(sec), datetime.datetime.now(), flush=True)
if is_in(cut_list, sec):
output_array[0].append(val_0)
output_array[1].append(val_1)
if sec > end:
break
#Tomber si vous n'utilisez pas asfortranarray
librosa.output.write_wav(
output_audio_file, np.asfortranarray(output_array), sr_full
)
def main():
audio_file = "full.mp3" #Audio vidéo extrait
voice_file = "voice.wav" #Extrait uniquement la voix de la vidéo
movie_file = "full.mp4"
output_audio_file = "cut.wav"
output_movie_file = "cut.mp4"
cut_type = "local_max" #Base de valeur maximale
# cut_type = "max" #Base de valeur maximale
cut_list = decide_cut_frames(cut_type, voice_file)
cut_movie(cut_list, movie_file, output_movie_file)
cut_audio(cut_list, audio_file, output_audio_file)
if __name__ == "__main__":
main()
Recommended Posts