[PYTHON] J'ai créé un fichier de sous-titres (SRT) à partir des données JSON d'AmiVoice

introduction

Je publierai pour la première fois. Je m'appelle Denki Sheep de Golden Bridge. Mon activité principale est la traduction en chinois, mais j'aime aussi la programmation comme passe-temps.

J'ai expérimenté des langages, mais je suis toujours programmeur du dimanche. Je veux que les professionnels me frappent de plus en plus!

Contexte

Récemment, en raison de l'influence de Corona, les interprètes sont particulièrement recherchés en ligne. Cela est souvent fait à l'avance dans le format d'enregistrement vidéo afin que la communication puisse devenir instable. En conséquence, non seulement la traduction mais aussi les ** sous-titres ** sont de plus en plus traités.

Jusqu'à présent, c'était une petite quantité, donc je devais le faire manuellement, mais comme c'était un gros problème, j'ai décidé de créer un fichier SRT pour économiser du travail.

À propos des fichiers SRT

Un format qui peut être considéré comme la norme de facto pour coller des sous-titres dans des vidéos. Le contenu est très simple.

1
00:00:01,050 --> 00:00:05,778
Premier sous-titre

2
00:00:07,850 --> 00:00:11,123
Sous-titre suivant

3
00:01:02,566 --> 00:01:12,456
Troisième sous-titre

comme, indice

Avec ce fichier, vous pouvez importer des sous-titres dans un fichier vidéo à la fois.

Transcription

Nous utilisons AmiVoice Cloud Platform pour les brouillons de transcription japonais.

Comme il a été fabriqué au Japon, il est plus précis que Google, etc. en japonais.

Ecrire à partir de zéro est difficile, donc [Exemple de programme](https://acp.amivoice.com/main/manual/%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab Juste tweak% e3% 83% 97% e3% 83% ad% e3% 82% b0% e3% 83% a9% e3% 83% a0 /).

En exécutant cet exemple de programme, vous pouvez obtenir les données JSON à reconnaissance vocale. Pour plus d'informations

[JSON renvoyé (AmiVoice)](https://acp.amivoice.com/main/manual/if%E4%BB%95%E6%A7%98-http%E9%9F%B3%E5%A3 % B0% E8% AA% 8D% E8% AD% 98api% E8% A9% B3% E7% B4% B0 / # réponse)

Clé Clé Clé La description
results Disposition du "résultat de la reconnaissance de la section vocale"
confidence Degré de fiabilité(Une valeur comprise entre 0 et 1. 0:Faible fiabilité, 1:Grande fiabilité)
starttime Heure de début de la parole (les données vocales commencent par 0)
endtime Heure de fin de la conversation (les données vocales commencent par 0)
tags Inutilisé (tableau vide)
rulename Inutilisé (caractère vide)
text Texte du résultat de la reconnaissance
tokens Disposition des éléments morphologiques du texte du résultat de la reconnaissance
written Notation des éléments morphologiques (mots)
confidence Fiabilité morphologique (probabilité de résultat de reconnaissance)
starttime Heure de début de la morphologie (les données vocales commencent par 0)
endtime Heure de fin de la morphologie (les données vocales commencent par 0)
spoken Lecture de la morphologie
utteranceid ID des informations de résultat de reconnaissance*1
text Le texte complet du résultat de la reconnaissance qui combine tous les "résultats de reconnaissance de la section vocale"
code Code à une lettre représentant le résultat*2 Liste des codes et messages contenus dans JSONvérification ...
message Chaîne de caractères représentant le contenu de l'erreur*2 Liste des codes et messages contenus dans JSONvérification ...

À partir de ces données JSON, utilisez l'heure de début, l'heure de fin et les jetons écrits pour les organiser au format SRT.

Lire JSON

Une fois que vous obtenez le JSON, nous commencerons la conversion immédiatement. Comme condition pour séparer les blocs de sous-titres

--Ponctuation (,?) --Time (millisecondes)

Je vais utiliser autour. De plus, je n'ajoute pas de signes de ponctuation aux sous-titres, je vais donc les ignorer.

Ces éléments sont des arguments de ligne de commande qui peuvent être modifiés de manière flexible.

import argparse
import json

parser = argparse.ArgumentParser()
parser.add_argument("file", help="Designate JSON file name to read")
parser.add_argument("-d", "--delimiters", help="Designate delimiters to separate subtitles. Default value is ['。','、']", default="。,、")
parser.add_argument("-s", "--skip", help="Designate skip words which do not inculud in subtitles. Default value is ['。','、']", default="。,、")
parser.add_argument("-t", "--time", help="Designate allowed time for single subtile by millisecongds. Default value is 5000", default=5000, type=int)
parser.add_argument("-c", "--charas", help="Designate allowed charas for single subtile. Default value is 25", default=25, type=int)

class SRTFomart():
	def __init__(self, args): 
		self.text = ""
		self.blocks = []
		self.delimiters = args.delimiters.split(",")
		self.skipWords = args.skip.split(",")
		self.time = args.time
		self.charas = args.charas

	def readFile(self, file):
		f = open(file, "r", encoding="utf-8")
		contents = f.read()
		f.close()
		data = json.loads(contents)["results"][0]
		self.text = data["text"]
		self.readTokens(data["tokens"])

	def readTokens(self, tokens):
		sub = ""
		startTime = 0
		index = 1
		# subTitles = []
		
		for token in tokens:
			written = token["written"]
			#Définissez startTime si le sous-titre est vide
			if sub == "":
				#Même si le sous-titre est vide, ignorez si le contenu du jeton est un signe de ponctuation
				if written in self.delimiters or written in self.skipWords:
					continue

				else:
					startTime = token["starttime"]

			#Créer des sauts de sous-titres
			#Stockez les sous-titres dans des blocs dans chaque condition et réinitialisez une fois
			#Si vous frappez un signe de ponctuation
			if written in self.delimiters or len(sub) > self.charas or token["endtime"] - startTime > self.time:
				self.blocks.append(self.createSRTBlock(index, startTime, token["endtime"], sub))
				sub = ""
				startTime = 0
				index += 1

			#Connecter les sous-titres sauf conditions
			else:
				if written not in self.skipWords:
					sub += token["written"]
		
		#Pour boucle jusqu'ici
		#Stocker le dernier bloc
		self.blocks.append(self.createSRTBlock(index, startTime, tokens[-1]["endtime"], sub))


	def createSRTBlock(self, index, startTime, endTime, sub):
		stime = self.timeFormat(startTime)
		etime = self.timeFormat(endTime)
		return f"{index}\n{stime} --> {etime}\n{sub}\n"

	def timeFormat(self, time):
		time_ = time
		ms_ = int(time_ % 1000)
		time_ = int((time_ - ms_) / 1000)
		sec_ = int(time_ % 60)
		time_ = int((time_ - sec_) / 60)
		mn_ = int(time_ % 60)
		time_ = int((time_ - mn_) /60)
		hr_ = int(time_ % 60)
		if ms_ < 10:
			ms = f"00{ms_}"
		elif ms_ < 100:
			ms = f"0{ms_}"
		else:
			ms = str(ms_)
				
		if sec_ < 10:
			sec = f"0{sec_}"
		else:
			sec = str(sec_)
				
		if mn_ < 10:
			mn = f"0{mn_}"
		else:
			mn = str(mn_)
				
		if hr_ < 10:
			hr = f"0{hr_}"
		else:
			hr = str(hr_)
	
		return f"{hr}:{mn}:{sec},{ms}"

	def exportSRTText(self):
		return "\n".join(self.blocks)


if __name__ == "__main__":
	args = parser.parse_args()
	if not args.file.endswith(".json"):
		print("Please set json file")
	
	else:
		srt = SRTFomart(args)
		srt.readFile(args.file)
		text = srt.exportSRTText()
		srtName = args.file.replace(".json", ".srt")
		f = open(srtName, "w", encoding="utf-8")
		f.write(text)
		f.close()
		print("done")


Vous avez réussi la conversion au format SRT.

importer

Enfin, tout ce que vous avez à faire est d'ajuster ou de traduire le fichier SRT généré et de l'importer dans votre logiciel de montage vidéo. Avec Davinci Resolve, je viens de le déposer du pool de médias sur la piste vidéo.

D'après le travail manuel jusqu'à présent, il semble que l'on puisse s'attendre à une amélioration considérable de l'efficacité!

à partir de maintenant

――Je souhaite me connecter à la traduction automatique!

Bonne chance pour créer des sous-titres pour la nouvelle ère normale!

Recommended Posts

J'ai créé un fichier de sous-titres (SRT) à partir des données JSON d'AmiVoice
J'ai créé un outil pour générer du Markdown à partir du fichier JSON Scrapbox exporté
J'ai essayé de lire les données d'un fichier en utilisant Node.js.
J'ai créé un fichier de configuration avec Python
J'ai fait un programme pour vérifier la taille d'un fichier avec Python
J'ai créé un fichier de dictionnaire python pour Neocomplete
J'ai créé un package pour créer un fichier exécutable à partir du code source Hy
〇✕ J'ai fait un jeu
Faire une copie d'un fichier Google Drive à partir de Python
Python --Lire les données d'un fichier de données numériques et calculer la covariance
J'ai créé une boîte de changement de seuil pour Pepper's Dialog
J'ai essayé d'exécuter python à partir d'un fichier chauve-souris
J'ai essayé de collecter des données sur un site Web avec Scrapy
Script Python qui crée un fichier JSON à partir d'un fichier CSV
J'ai créé un outil de génération de données texte répétitif "rpttxt"
J'ai créé un script en Python pour convertir un fichier texte pour JSON (pour l'extrait d'utilisateur vscode)
Je veux démarrer beaucoup de processus à partir de python
J'ai créé un outil pour créer un nuage de mots à partir de wikipedia
J'ai fait une fonction pour vérifier le modèle de DCGAN
J'ai fait une image ponctuelle de l'image d'Irasutoya. (partie 1)
Python> Lire à partir d'une chaîne multiligne au lieu d'un fichier> io.StringIO ()
J'ai fait une image ponctuelle de l'image d'Irasutoya. (partie 2)
Je vous ai fait exécuter des commandes depuis un navigateur WEB
Créer un fichier de données factice
J'ai fait un texte Python
J'ai fait un robot discord
J'ai créé un robot Line qui devine le sexe et l'âge d'une personne à partir de l'image
Quelles compétences devrais-je étudier en tant qu'analyste de données inexpérimenté?
Python> J'ai créé un code de test pour mon propre fichier externe
J'ai créé beaucoup de fichiers pour la connexion RDP avec Python
Impressions de toucher Dash, un outil de visualisation de données réalisé par python
J'ai fait un bot mou qui m'informe de la température
[python] J'ai créé une classe qui peut écrire rapidement une arborescence de fichiers
[Kaggle] J'ai fait une collection de problèmes en utilisant le didacticiel Titanic
J'ai créé un site d'apprentissage C ++
Puis-je être un data scientist?
J'ai fait un Line-bot avec Python!
J'ai créé un script de traduction basé sur CUI (2)
J'ai fait un wikipedia gacha bot
Extraire des données spécifiques d'un JSON complexe
J'ai fait une loterie avec Python.
J'ai créé un script de traduction basé sur CUI
J'ai créé un démon avec Python
J'ai créé un plugin pour générer une table Markdown à partir de csv avec Vim
[Mise à jour Ver1.3.1] J'ai créé une bibliothèque de prétraitement de données DataLiner pour l'apprentissage automatique
J'ai fait une note du colaboratoire Google qui peut utiliser Spleeter facilement.
J'ai fait une sorte d'outil de traitement d'image simple en langage Go.
L'histoire d'une personne qui a commencé à viser un data scientist depuis un débutant
J'ai fait une simple minuterie qui peut être démarrée depuis le terminal
J'ai fait GAN avec Keras, donc j'ai fait une vidéo du processus d'apprentissage.
J'ai essayé d'effectuer une analyse de cluster de clients à l'aide des données d'achat
J'ai fait une erreur en récupérant la hiérarchie avec MultiIndex of pandas
J'ai fait une webAPI! Construire un environnement à partir de Django Rest Framework 1 avec EC2
J'ai créé une fonction pour voir le mouvement d'un tableau à deux dimensions (Python)
J'ai créé un script pour vérifier si l'anglais est entré dans la position spécifiée du fichier JSON en Python.
J'ai créé un programme en Python qui lit les données FX CSV et crée un grand nombre d'images de graphiques