[PYTHON] Je veux trouver automatiquement des pièces de haute qualité à partir des vidéos que j'ai tournées

Chose que tu veux faire

approche

Relation

La source

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()

Remarques

Recommended Posts

Je veux trouver automatiquement des pièces de haute qualité à partir des vidéos que j'ai tournées
Je souhaite calculer le temps d'arrêt autorisé à partir du taux de fonctionnement
Je veux épingler Spyder à la barre des tâches
Je veux sortir froidement sur la console
Je veux gérer la rime part1
Je veux gérer la rime part3
Je veux utiliser jar de python
Je veux afficher la barre de progression
Je veux gérer la rime part2
Je veux gérer la rime part5
Je veux gérer la rime part4
Je souhaite envoyer un signal uniquement du sous-thread au thread principal
Je souhaite me connecter à PostgreSQL à partir de plusieurs langues
Je souhaite envoyer un e-mail depuis Gmail en utilisant Python.
[Python] Je veux gérer 7DaysToDie depuis Discord! 1/3
Je veux gérer la rime part7 (BOW)
Je veux faire des crises de ma tête
Je veux utiliser le solveur ceres de python
[Python] Je veux gérer 7DaysToDie depuis Discord! 2/3
Je veux trouver facilement une délicieuse boutique
Je veux créer du code C ++ à partir de code Python!
Je souhaite personnaliser l'apparence de zabbix
Je souhaite utiliser la fonction d'activation Mish
Je veux afficher la progression en Python!
[LINE Messaging API] Je souhaite envoyer un message du programme à tout le monde LINE
[Ansible] Je souhaite appeler ma propre fonction à partir du module de modèle (macro)
Je veux détecter des images de chats d'Instagram
J'ai essayé de détecter l'iris à partir de l'image de la caméra
Je veux grep le résultat de l'exécution de strace
Je veux faire défiler la table de décalage Django, mais ...
[Python] J'ai créé un système pour introduire "la recette que je veux vraiment" depuis le site de recettes!
Je veux trouver un package populaire sur PyPi
Je voulais utiliser la bibliothèque Python de MATLAB
Je veux hériter de l'arrière avec la classe de données python
Je veux bien comprendre les bases de Bokeh
Je veux juste trouver l'intervalle de confiance à 95% de la différence de ratio de population en Python
Je veux écrire en Python! (3) Utiliser des simulacres
Je souhaite envoyer automatiquement un e-mail de création d'entreprise
Je veux gérer la rime part6 (organiser une fois)
Je veux automatiser ssh en utilisant la commande expect!
Je souhaite publier le produit au moindre coût
J'ai lu la référence Chainer (mise à jour de temps en temps)
Je veux utiliser le jeu de données R avec python
Je veux gérer la rime part8 (fini une fois)
Je veux faire Wake On LAN de manière entièrement automatique
Je souhaite augmenter la sécurité de la connexion SSH
Je veux changer la destination du lien symbolique de / lib64 de / usr / lib64 à / my-lib64 sur CentOS
Je veux trouver l'intersection d'une courbe de Bézier et d'une ligne droite (méthode de découpage de Bézier)
J'ai créé un outil pour générer automatiquement un simple diagramme ER à partir de l'instruction CREATE TABLE
[Selenium] Je souhaite afficher le navigateur en appuyant sur le pilote du système d'exploitation hôte à partir de WSL
J'ai essayé de trouver la tendance du nombre de navires dans la baie de Tokyo à partir d'images satellites.
J'ai essayé de découvrir les grandes lignes de Big Gorilla
[TensorFlow] Je souhaite maîtriser l'indexation pour Ragged Tensor
Je veux utiliser la dernière version de gcc même si je n'ai pas les privilèges sudo! !!
Je souhaite enregistrer les photos envoyées par LINE vers S3
J'ai essayé de trouver la moyenne de plusieurs colonnes avec TensorFlow