Eingang
Ausgabe (Wenn Sie es tatsächlich verwenden, kombinieren Sie die folgenden zwei Dateien mit ffmpeg oder einer Videobearbeitungssoftware.)
cut_movie.py
import datetime
import os
import cv2
import librosa
import numpy as np
import scipy
#Eine Funktion, die auf nette Weise an die Konsole ausgegeben werden kann. Es muss nicht sein.
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])
#Funktion zum Überprüfen, ob die Zielanzahl von Sekunden das Ziel des Clippings ist
def is_in(tuple_list, val):
for tup in tuple_list:
if tup[0] <= val <= tup[1]:
return True
return False
#Verwenden Sie diese Option beim Zuschneiden basierend auf dem Maximalwert
def cut_by_max_rms(rms, percentile):
is_on = False
start = 0
end = 0
threshold = np.percentile(rms[0], percentile)
cut_list = []
#Wenn der vorherige Frame auch zum Zuschneiden ausgewählt wurde, kombinieren Sie die Zuschneidebereiche
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
#Verwenden Sie dies für die maximale Punktbasis
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
#Identifizierung der Aussparungsstelle
#Je nach Lautstärke ausschneiden
def decide_cut_frames(cut_type, voice_file):
#Laden Sie Audio, um Pflanzen zu identifizieren
#Ich möchte es so leicht wie möglich machen, also lese ich es mit einer Abtastrate von 8000
y_voice, sr_voice = librosa.load(voice_file, sr=8000, mono=True)
#Überprüfen Sie die Lautstärke alle 30 Sekunden
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":
#Die Lautstärke ist maximal(Wo der Gipfel steht)Wählen Sie bis zu 20 Bilder aus und schneiden Sie sie aus
cut_list = cut_by_local_max_rms(rms, 20)
elif cut_type == "max":
#Top 5 am lautesten%Schneiden Sie den Rahmen aus
cut_list = cut_by_local_max_rms(rms, 100 - 95)
return cut_list
#Videoausschnitt
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 bei der Ausgabe
#Beachten Sie, dass sich dies je nach Betriebssystem ändern kann
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
#Wenn es bereits vorhanden ist, tritt ein Fehler auf. Löschen Sie ihn daher einmal.
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)
#Lesen Sie Frame für Frame von Anfang bis Ende, wenn das Ende überschritten wird
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
#Fügen Sie Text für die aktuelle Zeit hinzu
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()
#Audio-Zuschnitt
def cut_audio(cut_list, voice_file, output_audio_file):
#Beachten Sie, dass sr 22050 ist, wenn Keine angegeben ist.
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
#Fallen Sie, wenn Sie kein Fortranarray verwenden
librosa.output.write_wav(
output_audio_file, np.asfortranarray(output_array), sr_full
)
def main():
audio_file = "full.mp3" #Extrahiertes Video-Audio
voice_file = "voice.wav" #Nur Sprache aus Video extrahiert
movie_file = "full.mp4"
output_audio_file = "cut.wav"
output_movie_file = "cut.mp4"
cut_type = "local_max" #Maximalwertbasis
# cut_type = "max" #Maximalwertbasis
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