[PYTHON] Données de sous-titres créées avec Amazon Transcribe

Déclencheur

J'ai acheté une boîte de DVD de "Mayday!: La vérité et la vérité des accidents d'avion" (titre anglais Air Crash Investigation). C'est une version anglaise, mais je pensais qu'il y aurait des sous-titres, mais je n'avais même pas de sous-titres anglais ...

Heureusement, le contrôle d'accès par CSS (Content Scramble System) n'était pas appliqué, j'ai donc essayé de créer des sous-titres d'une manière ou d'une autre.

Ce que j'ai fait

  1. Extraire uniquement l'audio des données vidéo (ffmpeg)
  2. Transcrire à partir de données vocales (Amazon Transcribe)
  3. Convertissez le résultat de la transcription en données de sous-titres SubRip (Python)
  4. Incorporer les données de sous-titres dans les données vidéo (mkvmerge)

Installation des outils nécessaires

Pour macOS, vous pouvez l'installer à l'aide de homebrew. Il est également nécessaire que vous puissiez utiliser Python 3 et pip.

brew install ffmpeg mkvtoolnix
pip3 install boto3

1. Extraire uniquement l'audio des données vidéo

Avec ffmpeg, vous pouvez facilement copier dans un fichier contenant uniquement des données audio.

ffmpeg -i original.m4v -acodec copy -vn output.m4a

2. Transcription à partir des données vocales

Pour utiliser Amazon Transcribe, vous devez télécharger des données audio sur S3. Cette fois, pour plus de simplicité, j'ai écrit un script simple en Python qui se télécharge simplement sur S3 et soumet une tâche à Amazon Transcribe.

Le code qui sort après ceci est un code que j'ai écrit en un peu plus de 10 minutes, donc c'est assez approximatif dans l'ensemble ...

01-transcribe.py


from boto3 import client, resource
import os
import sys

AWS_ACCESS_KEY = "hogehoge"
AWS_SECRET_ACCESS_KEY = "fugafuga"
BUCKET = "somebucket"

def upload(filepath):
    basename = os.path.basename(filepath)

    s3_client = resource(
        "s3",
        region_name="ap-northeast-1",
        aws_access_key_id=AWS_ACCESS_KEY,
        aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
    )
    s3_client.Bucket(BUCKET).upload_file(filepath, basename)


def transcribe(filename):

    url = "s3://{}/{}".format(BUCKET, filename)

    transcribe_client = client(
            "transcribe",
            region_name="ap-northeast-1",
            aws_access_key_id=AWS_ACCESS_KEY,
            aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
    )
    response = transcribe_client.start_transcription_job(
            TranscriptionJobName=filename,
            LanguageCode="en-US",
            MediaFormat="mp4",
            Media={
                    "MediaFileUri": url
            },
            OutputBucketName=BUCKET,
    )

def main():
    filepath = sys.argv[1]
    upload(filepath)
    transcribe(os.path.basename(filepath))


if __name__ == "__main__":
    main()

Passez le fichier précédent comme argument et exécutez.

python 01-transcribe.py output.m4a

Téléchargez le fichier JSON résultant à partir de la console Web. (Omission)

3. Convertissez le résultat de la transcription en données de sous-titres SubRip

Le JSON résultant contient un tableau de mots reconnus et leurs heures de début et de fin. Si vous affichez chaque mot comme un sous-titre tel quel, il sera trop difficile à lire.

Par conséquent, j'ai décidé de générer des données de sous-titres (srt) en décidant de la plage d'affichage selon certaines règles.

Cette règle est décidée de manière appropriée, alors jouez avec elle comme vous le souhaitez.

02-makesrt.py


import json
import sys


def sec2time(sec):
    h = int(sec/3600)
    m = int((sec%3600) / 60)
    s = int(sec % 60)
    mils = int((sec%1)*1000)
    return "{:02d}:{:02d}:{:02d},{:03d}".format(h, m, s, mils)

def convert2srt(filepath):
    with open(filepath, "r") as f:
        data = json.load(f)

    start_time = 0
    end_time = 0
    s = ""
    index = 0
    for item in data["results"]["items"]:
        is_output = False

        if "start_time" in item:
            item["start_time"] = float(item["start_time"])
            item["end_time"] = float(item["end_time"])

            if item["start_time"] - end_time > 3:
                #As-tu eu le temps
                is_output = True

            elif len(s) >= 110:
                #Si ça s'allonge
                is_output = True
            
            if s != "":
                if len(s)>1 and s[-2].isupper():
                    pass
                else:
                    last = s[-1]
                    if last in (".", "?", "!"):
                        is_output = True
                    
                    if last == "," and len(s) > 80:
                        is_output = True

        if is_output:

            end_time = min(item["start_time"], end_time+2.0)

            if s != "":
                print(index)
                index += 1
                print("{0} --> {1}".format(sec2time(start_time), sec2time(end_time)))
                print(s)
                print("")

            start_time = 0
            end_time = 0
            s = ""

        if "start_time" in item:
            if start_time == 0:
                start_time = item["start_time"]
            end_time = item["end_time"]
            if s and (len(item["alternatives"][0]["content"])>1 or s[-1] != "."):
                s += " " + item["alternatives"][0]["content"]
            else:
                s += item["alternatives"][0]["content"]
        else:
            s += item["alternatives"][0]["content"]

    if s != "":
        print(index)
        index += 1
        print("{0} --> {1}".format(sec2time(start_time), sec2time(end_time+2.0)))
        print(s)
        print("")

def main():
    filepath = sys.argv[1]
    convert2srt(filepath)

if __name__ == "__main__":
    main()

Spécifiez un fichier JSON comme argument et enregistrez le résultat dans un fichier texte par redirection.

python 02-makesrt.py result.json > result.srt

La sortie devrait ressembler à ceci

output


64
00:06:00,139 --> 00:06:16,839
Then the next Nano second, it was pure, unadulterated pandemonium Way number three going down.

65
00:06:16,839 --> 00:06:18,720
It looks like we lost number three engine.

66
00:06:18,720 --> 00:06:23,149
We're descending rapidly coming back.

4. Incorporer les données de sous-titres dans les données vidéo

Vous pouvez facilement intégrer des données de sous-titres dans un fichier mkv à l'aide de mkvmerge.

mkvmerge -o output.mkv original.m4v --language 0:eng --track-name 0:English result.srt

Les sous-titres intégrés peuvent être affichés lors de la lecture sur VLC.

résultat

Eh bien, je pense qu'il est affiché presque sans aucune gêne.

vlcsnap-2020-03-03-00h47m23s630.png

vlcsnap-2020-03-03-00h50m06s662.png

Le vrai plaisir de la programmation est que vous pouvez créer rapidement des outils à de tels moments.

Recommended Posts

Données de sous-titres créées avec Amazon Transcribe
Exemple de données créées avec python
Obtenez des données alimentaires avec l'API Amazon (Python)
Analyse de données avec python 2
Lecture de données avec TensorFlow
Manipulation des données avec les Pandas!
Mélangez les données avec les pandas
Augmentation des données avec openCV
Normariser les données avec Scipy
Analyse de données avec Python
CHARGER DES DONNÉES avec PyMysql
Un diagramme de réseau a été créé avec les données du COVID-19.
Incorporer des données audio avec Jupyter
Graphique des données Excel avec matplotlib (1)
Génération artificielle de données avec numpy
Extraire les données Twitter avec CSV
Obtenez des données Youtube avec python
Reconnaissance faciale par Amazon Rekognition
Apprenez de nouvelles données avec PaintsChainer
Binariser les données photo avec OpenCV
Graphique des données Excel avec matplotlib (2)
Utilisez Django pour enregistrer les données de tweet
Obtenez "Bals" avec Amazon Echo
Conseils de traitement des données avec Pandas
Lire des données json avec python