はじめに
最近AWSでつくるAIプログラミング入門という本をやっています。
この本が書かれたのは、2019年末で当初は英語でしか動かなかったシステムも今では日本語で動くようになっているものがいくつかあります。
その中にAmazon Transcribeがあり、日本語で本書のコードの一部を変更して対応させていましたが、エラーに遭遇したので今回はまとめたいと思います。
問題
以下のコードを実行したところエラーになりました。
このコードは本書のコードを一部変更したものになります。
import boto3
import json
import pprint
import time
import uuid
import urllib
bucket = str(uuid.uuid1())
print('bucket:', bucket)
region = 'ap-northeast-1'
s3 = boto3.client('s3', region)
result = s3.create_bucket(
Bucket=bucket,
CreateBucketConfiguration={'LocationConstraint': region})
file = 'scribe_file_in.mp3'
key = 'input'
s3.upload_file(file, bucket, key)
transcribe = boto3.client('transcribe', region)
job = str(uuid.uuid1())
uri = 'https://s3-'+region+'.amazonaws.com/'+bucket+'/'+key
result = transcribe.start_transcription_job(
TranscriptionJobName=job, Media={'MediaFileUri': uri},
MediaFormat='mp3', LanguageCode='ja-JP')
print('start_transcription_job:')
pprint.pprint(result)
start = time.time()
while True:
result = transcribe.get_transcription_job(TranscriptionJobName=job)
status = result['TranscriptionJob']['TranscriptionJobStatus']
if status != 'IN_PROGRESS':
break
time.sleep(10)
print('time:', time.time()-start)
print('get_transcription_job:')
pprint.pprint(result)
uri = result['TranscriptionJob']['Transcript']['TranscriptFileUri']
print('uri:', uri)
with urllib.request.urlopen(uri) as file_in:
transcripts = json.load(file_in)
with open('scribe_file_out.json', 'w', encoding='utf-8') as file_out:
json.dump(transcripts, file_out, indent=4)
print('transcript:')
for transcript in transcripts['results']['transcripts']:
print(transcript['transcript'])
transcribe.delete_transcription_job(TranscriptionJobName=job)
s3.delete_object(Bucket=bucket, Key=key)
s3.delete_bucket(Bucket=bucket)
変更点は以下の2点です。
1. regionがus-east-2
からap-northeast-1
に変更
2. transcribe.start_transcription_jobのLanguageCodeがen-US
からja-JP
に変更
同じディレクトリには、ボイスレコーダーで自分の声を録音したscribe_file_in.m4a
をscribe_file_in.mp3
にJupyterNotebook上で名前を変更しました。
すると、以下のエラーが出ます。
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-19-68aeffcf87d9> in <module>
38 pprint.pprint(result)
39
---> 40 uri = result['TranscriptionJob']['Transcript']['TranscriptFileUri']
41 print('uri:', uri)
42 with urllib.request.urlopen(uri) as file_in:
KeyError: 'TranscriptFileUri'
解決方法
resultをみたところ、以下のようになっていました。
{'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive',
'content-length': '562',
'content-type': 'application/x-amz-json-1.1',
'date': 'Mon, 31 May 2021 13:48:28 GMT',
'x-amzn-requestid': 'fd6eb86c-4668-4f0d-8af6-6847b09f9c40'},
'HTTPStatusCode': 200,
'RequestId': 'fd6eb86c-4668-4f0d-8af6-6847b09f9c40',
'RetryAttempts': 0},
'TranscriptionJob': {'CreationTime': datetime.datetime(2021, 5, 31, 13, 48, 19, 219000, tzinfo=tzlocal()),
'FailureReason': 'The media format that you specified '
"doesn't match the detected media "
'format. Check the media format and try '
'your request again.',
'LanguageCode': 'ja-JP',
'Media': {'MediaFileUri': 'https://s3-ap-northeast-1.amazonaws.com/da8910de-c216-11eb-8f7b-0242ac190002/input'},
'MediaFormat': 'mp3',
'Settings': {'ChannelIdentification': False},
'Transcript': {},
'TranscriptionJobName': 'db3498b4-c216-11eb-8f7b-0242ac190002',
'TranscriptionJobStatus': 'FAILED'}}
この中の以下の箇所をみると、Transcript
が空({})となっていました。
'MediaFormat': 'mp3',
'Settings': {'ChannelIdentification': False},
'Transcript': {},
空になっているので、そもそも文字おこし自体が失敗しています。
これが、`KeyError: 'TranscriptFileUri'の原因でした。
ちなみに以下の箇所がFAILED
になっているので失敗していることがわかります。
'TranscriptionJobStatus': 'FAILED'}}
この処理は、非同期で行われます。このコードではCOMPLETED
になるまで繰り返し表示がありますが、そのようなコードにしていない場合は、何度か実行してCOMPLETEDになるまで待つ必要があります。
では、なぜFAILED
になっているのでしょうか。
それは、.m4a
を.mp3
に変えたことでした。
.m4a
をアップロードしてFormatをmp4
にしても動きます。
以下のコードで解決しました。
import boto3
import json
import pprint
import time
import uuid
import urllib
bucket = str(uuid.uuid1())
print('bucket:', bucket)
region = 'ap-northeast-1'
s3 = boto3.client('s3', region)
result = s3.create_bucket(
Bucket=bucket,
CreateBucketConfiguration={'LocationConstraint': region})
file = 'scribe_file_in.m4a'
key = 'input'
s3.upload_file(file, bucket, key)
transcribe = boto3.client('transcribe', region)
job = str(uuid.uuid1())
uri = 'https://s3-'+region+'.amazonaws.com/'+bucket+'/'+key
result = transcribe.start_transcription_job(
TranscriptionJobName=job, Media={'MediaFileUri': uri},
MediaFormat='mp4', LanguageCode='ja-JP')
print('start_transcription_job:')
pprint.pprint(result)
start = time.time()
while True:
result = transcribe.get_transcription_job(TranscriptionJobName=job)
status = result['TranscriptionJob']['TranscriptionJobStatus']
if status != 'IN_PROGRESS':
break
time.sleep(10)
print('time:', time.time()-start)
print('get_transcription_job:')
pprint.pprint(result)
uri = result['TranscriptionJob']['Transcript']['TranscriptFileUri']
print('uri:', uri)
with urllib.request.urlopen(uri) as file_in:
transcripts = json.load(file_in)
with open('scribe_file_out.json', 'w', encoding='utf-8') as file_out:
json.dump(transcripts, file_out, indent=4)
print('transcript:')
for transcript in transcripts['results']['transcripts']:
print(transcript['transcript'])
transcribe.delete_transcription_job(TranscriptionJobName=job)
s3.delete_object(Bucket=bucket, Key=key)
s3.delete_bucket(Bucket=bucket)
データはボイスレコーダーでつくられたファイル形式そのままです。
これで動きました。
さいごに
AWSのエラーは割と起きると解決までたどり着くのが難しい気がしています。
あまり、解決のための記事というのが日本語ではすくなく、全体としても少ないです。
直接問い合わせるのがよさそうですね。