背景介绍
去年,从天而降的疫情给咱们的生存和学习, 带来了极大的影响。一方面须要缩小人员汇集、升高疫情流传危险, 同时又须要兼顾好日常工作推动, 很多客户把线下会议转移到线上举办,亚马逊云科技也不例外。尤其是去年底的 re:Invent 2020, 前所未有采纳收费线上会议的形式举办,同时,为了中国客户更好的观看体验,咱们也推出了本地化的亚马逊 re:Invent 国内站点,不便国内的客户观看,置信不少的粉丝曾经通过国内的站点观看了最新的 fable 和技术画。
因为 re:Invent 在寰球次要采纳英语进行直播,尤其是来自不同国家的英语口音对国内的开发者去学习和理解 re:Invent 的技术内容会有较大的挑战。在收到寰球站点传来视频之后,咱们既须要第一工夫在国内站点播出,又心愿可能为中国客户和开发者的体验减少英文字幕,这就须要咱们能极短的工夫内为每天新增的数十个甚至上百个视频减少英文字幕。在以往,为一个 1 小时的英文视频减少字幕,就须要翻译人员数小时的工作,去听取英文文本,同时还须要借助一些业余的工具,为听录的文本减少时间轴,这个过程老本极高,也无奈满足咱们第一工夫心愿可能公布的需要。
仔细的小伙伴们可能曾经发现了,在国内站点的视频英文字幕后面都有一句话:“字幕由 Amazon Transcribe 服务提供”,那么这是一个怎么神奇的服务,又是如何疾速帮忙咱们解决视频的英文字幕问题呢?
Amazon Transcribe 是一项主动语音辨认 (ASR) 服务,让开发人员可能轻松地为其应用程序增加语音转文本性能,他能够反对多种语言的语音辨认服务,其中包含英文和中国普通话的反对,而且在北京区域(BJS)和宁夏区域(ZHY)也已反对该项服务。
为了让国内的客户和粉丝可能第一工夫看到 re:Invent 视频,很多时候从拿到数十个视频到公布,只有几个小时,这么短啊的工夫,咱们是如何借助 Amazon Transcribe 来为每天上线的英文视频减少字幕呢?上面我就介绍一下,这个简略易用,无服务器架构的主动生成字幕的解决方案。如果您也刚好有一个同样的需要,能够间接用起来噢!
体系架构
示例的总体架构如下图所示:
- 上传视频文件到 Amazon S3 存储桶,能够选定一个特定的文件夹;
- Amazon S3 监测到存储桶中某个文件夹有新增的文件,触发 lambda 函数;
- Lambda 函数调用 Amazon Transcribe 服务,生成视频对应的文本(json 格局);
- 对字幕文本进行格局转换,生成反对播放器的字幕文件格式(srt);
- 上传字幕文件到存储桶指定的文件夹中。
实现过程
1. 创立 S3 存储桶
首先在亚马逊云科技治理控制台进入”S3“服务,点击“创立存储桶”, 输出存储桶的名称,点击“创立”按钮创立一个 s3 存储桶。并且在新创建的桶里,点击“创立文件夹“,创立一个名字叫做“videos”的文件夹用于寄存咱们的视频文件。
留神这里咱们新建一个文件夹寄存须要加载字幕的视频,而不是间接把视频放到桶里,这样能够防止咱们的 Lambda 函数被本人生成的字幕文件循环调用。
2. 创立 IAM 角色
每个 Lambda 函数都有一个与之关联的 IAM 角色。此角色定义容许该性能与其进行交互的其余 Amazon Web Services 服务。在本示例中,您须要创立一个 IAM 角色,授予您的 Lambda 函数权限,以便与 Transcribe 服务以及在上一步中创立的 S3 服务进行交互。
在 Amazon Web Services 治理控制台中,单击“服务”,而后抉择“IAM”。在左侧导航栏中抉择“角色”,而后抉择“创立角色”,顺次抉择“AWS 产品”,“Lambda”作为角色类型,而后单击“下一步:权限”按钮,在“筛选策略”抉择“AmazonS3FullAccess”,“AWSLambda_FullAccess”和“AmazonTranscribeFullAccess”,点击“下一步:审核”,中角色名称中输出“addSubtitleRole”,点击“创立角色”。
3. 创立 Lambda 函数
在 Amazon Web Services 治理控制台进入“Lambda”服务,点击“创立函数”按钮。在“函数名称”中填写函数名称,在“运行时”的抉择框中抉择“Python 2.7”。这里要特地留神,咱们抉择更改默认执行角色,在“执行角色”中抉择“应用现有角色”,而后抉择刚刚创立的角色名称,点击“创立函数”按钮实现函数的创立。在此示例中,咱们抉择了 Python 2.7 作为开发环境,并为该 Lambda 函数赋予了上一步创立的角色。
4. 配置触发条件
在 Lambda 的函数配置页面,点击“增加触发器”按钮增加触发条件。抉择“s3”。
在触发条件配置页面,在“存储桶”下拉列表中抉择刚刚创立的存储桶名称,在“事件类型”下拉列表中抉择“Put”,在“前缀”中输出“videos/”(留神这里要有“/”),在“后缀”中输出“.mp4”, 而后点击“增加”按钮,实现触发条件的增加。该触发条件设置监督刚刚创立存储桶的 videos 目录中扩大名为.mp4 的
文件,如果新增一个视频,将触发该 lambda 函数。
5. Lambda 内存和超时配置
在刚创立的 Lambda 函数中,咱们须要配置了内存的大小和执行超时。因为 Lambda 函数会调用 Transcribe 服务进行文字提取,因而不须要批改内容的大小,默认值为 128MB。示例中咱们采纳的视频文件的时长均在半小时内,Transcribe 的解决工夫通常不会超过 10 分钟,在这里咱们设置超时时长“Timeout”为 10 分钟。
6. 导入 Lambda 函数
关上附件中的 python 文件,将其内容粘贴在 Lambda 函数实现的区域,点击右上角的“Deploy”按钮。
Lambda 的实现次要包含以下几个步骤:
6.1. 参数获取
从 event 对象中和零碎变量中获取相干参数信息。
region:以后区域, 示例中应用的是区域是宁夏区域
bucket_name:存储桶名称,您刚刚创立的存储桶名称
sourceS3Key:视频文件的 key 值。这里是咱们方才所设置的监测 videos 目录下的 mp4 类型的文件,key 值为 videos/*.mp4
fn:依据 sourceS3Key 提取文件名。
dir:依据 sourceS3Key 提取目录名。
6.2. 调用 Transcribe 工作
- 为每个工作 job_name 创立惟一的标识
- 调用 starttranscriptionjob,上面的代码中介绍了每个参数以及含意
- 因为调用的 job 是异步工作,咱们通过轮训的办法检测 job 的返回后果
生成转换工作的工夫戳
now=int(time.time())
job_name = "conv-"+str(now)
右滑查看残缺代码
启动转换工作
MediaFileUri: 媒体门路,示例采纳 s3 的门路
MediaFormat: 媒体格式,目前反对 mp3,mp4,wav,flac
LanguageCode: 媒体的语言编码,咱们的视频是英文的,设置为 en-US
`
transcribe = boto3.client(‘transcribe’)
transcribe.start_transcription_job(
TranscriptionJobName=job_name,
Media={‘MediaFileUri’: job_uri},
MediaFormat=’mp4′,
LanguageCode=’en-US’
)
右滑查看残缺代码
#转换须要肯定的工夫,这里进行轮训检测处理结果。您也能够通过控制台查看工作状态。```
while True:
status = transcribe.get_transcription_job(TranscriptionJobName=job_name)
if status['TranscriptionJob']['TranscriptionJobStatus'] in ['COMPLETED', 'FAILED']:
break
print("Transcribe is processing...")
time.sleep(5)
右滑查看残缺代码
6.3. 生成 srt 字幕文件
Transcribe所抓取转化的字幕 json 数组中,蕴含每个字(或者词语)的开始工夫,完结工夫,置信度等信息。上面咱们须要把 json 数组转换成字幕文件。常见的字幕格局是 SRT 格局。SRT 的格局非常简单:一句工夫代码 + 一句字幕。
`
if (status’TranscriptionJob’==’COMPLETED’):
url=status’TranscriptionJob'[‘TranscriptFileUri’]
text=downloadJson(url)
sJson = json.loads(text)
output=process(sJson”results”)
uploadResult(region,bucket_name,dir+’/output/’+fn, output)
return {
‘statusCode’: 200,
‘body’: json.dumps(‘Process complete’)
}
右滑查看残缺代码
#### **6.4. 转换为 srt 格局字幕 **
函数 process()将上一步的 json 文件转换成 srt 格局的字幕文件,具体处理过程如下。```
def process(items):
i=1
output=''
isStart=False
isEnd=False
start_time=0
end_time=0
msg=''
for index, item in enumerate(items):
if (not item.has_key('start_time')):
msg=msg+item['alternatives'][0]['content'] + ' '
else:
end_time=float(item['end_time'])
if (end_time-start_time>4.0 or index+1==len(items)):
isEnd=True
if (not isStart and item.has_key('start_time')):
isStart=True
start_time=float(item['start_time'])
msg=msg+item['alternatives'][0]['content'] + ' '
output=output+str(i)+'\n'
continue
if (isStart and not isEnd and item.has_key('start_time')):
msg=msg+item['alternatives'][0]['content'] + ' '
if (isStart and isEnd):
hour=int(start_time/60/60)
min=int(start_time/60)-hour*60
sec=int(start_time)-min*60-hour*60*60
msec=int((start_time-sec)*1000)
e_hour=int(end_time/60/60)
e_min=int(end_time/60)-e_hour*60
e_sec=int(end_time)-e_min*60-e_hour*60*60
e_msec=int((end_time-sec)*1000)
msg1='{}:{}:{},{} --> {}:{}:{},{}'.format(hour,min,sec,msec, e_hour,e_min,e_sec,e_msec)+'\n'
output=output+msg1+msg+item['alternatives'][0]['content']+'\n\n'
i=i+1
isStart=False
isEnd=False
start_time=end_time
msg=''
return output
右滑查看残缺代码
6.5. 上传后果到 S3
最初咱们将 srt 文件上传到 s3,本示例中,咱们设置了 video/output 作为其输入的存储门路。
def uploadResult(region,bucket_name,fn,body):
s3 = boto3.client(service_name='s3',region_name=region)
s3.put_object(Bucket=bucket_name, Key=fn[0:-4]+'.srt', Body=body) #remove .mp4
右滑查看残缺代码
7. 测试
在治理控制台点击“S3”服务,关上刚创立的存储桶,进入“videos”目录,点击“上传”“增加文件”从本地电脑里抉择一个视频文件,点击“上传”。此时就会触发咱们刚刚创立的 Lambda 函数。咱们能够在“Amazon Transcribe”察看 job 的执行状况。点击任何一个 job 的名称,能够显示 job 的详细信息。当 job 的状态显示为“实现”,进入到 S3 存储桶的“输入”目录,您会惊喜的发现,字幕文件曾经生成了。
上面咱们看一下成果吧。看起来成果还是不错的,除了一些技术词汇可能有些偏差,大部分的对话都能够残缺的听录下来 。如果须要字幕内容须要翻译,这也是一个很好的终点,能够 极大的升高翻译人员的工作量。
老本剖析
做了这么多,咱们须要破费多少钱呢?亚马逊云科技官网很贴心的为大家做了一个罕用案例的老本剖析:
依照下面的假如,Amazon Transcribe 解决一个半小时左右的网络研讨会,大略只须要人民币 4.86 元。
总结
通过应用无服务器架构的Amazon Transcribe,联合 Amazon Lambda 和 Amazon S3,用户能够不便的在视频解决的各种场景中,无需购买服务器,不便疾速的构建本人的视频字幕转换利用。
下面的案例是一个咱们在理论场景利用的简化版,适宜短视频的解决。然而,在理论的使用中,因为局部视频工夫较长,比方 keynote 可能长达 3 - 4 个小时,如果咱们采纳当初的架构,就会呈现 Lambda 超时的问题。对于长视频的解决,咱们就须要优化架构。
限于篇幅,具体的办法在本博客中不再赘述,然而小伙伴们能够动起来手来,改良当初的架构,比方把咱们的 Lambda 利用分成两个局部,当初的局部仅仅用来启动 Transcribe 的工作,不再轮询去期待工作的实现。
而采纳 CloudWatch event 来监听 Transcribe job 状态的变动,从而触发另一个 lambda 解决生成的 JSON 格局的字幕文件转化成一个 SRT 的格局,这样既能够防止超时的产生,同时也升高了 Lambda 服务轮询所产生的老本。
本篇作者
李昕 Leon Li
亚马逊云科技资深产品市场经理
全面负责亚马逊云科技在人工智能,机器学习,数据库,大数据和物联网等无关的云服务的产品营销和推广。在退出亚马逊云科技之前,曾服务于 Apple,Oracle,Lenovo 等世界出名跨国企业,涵盖产品战略规划和行业利用等多个畛域。
王凯 Kai Wang
亚马逊云科技解决方案架构师
负责基于亚马逊云科技云计算计划架构的征询和设计,推广 亚马逊云科技云平台技术和各种解决方案。在退出亚马逊云科技之前,曾服务于 Huawei,Alibaba 等世界知名企业,负责视频云、边缘计算解决方案和架构设计,在直播、音视频通信、CDN 畛域有丰盛教训。