• 1

  • 1

  • 收藏

自制“看剧神器”——用 Amazon Transcribe 快速翻译视频英文字幕!

ONLY、me

关注计算机

5天前

在去年底举办的亚马逊 re:Invent 2020 上,为了中国客户更好的观看体验,我们也推出了本地化的亚马逊 re:Invent 国内站点。

细心的小伙伴们可能已经发现了,在亚马逊 re:Invent 中国网站的演讲视频英文字幕前都有这样一句话:“字幕由 Amazon Transcribe 服务提供”,从演讲视频上线到高效完成英文字幕的本地化,竟然只需要短短几个小时的时间,这到底是一个怎样神奇的服务?今天我们就来一起好好“认识”它!

案例背景小科普

由于亚马逊 re:Invent 在全球主要采用英语进行直播,尤其是来自不同国家的英语口音对国内的开发者去学习和了解 re:Invent 的技术内容会有较大的挑战。

在以往,为一个 1 小时的英文视频增加字幕,就需要翻译人员数小时的工作,去听取英文文本,同时还需要借助一些专业的工具,为听录的文本增加时间轴,这个过程成本极高,也无法满足高时效性的发布需求。

为了让国内的客户和粉丝能够第一时间看到亚马逊 re:Invent 带中文字幕的演讲视频,从拿到数十个视频到发布,只有短短几个小时的时间。即使在如此紧缩的时间内,Amazon Transcribe 也能成功地为每天上线的英文演讲视频提供高效的字幕翻译服务!

下面我们来就介绍一下,Amazon Transcribe 这个简单易用的,由无服务器架构自动生成字幕的解决方案。如果您也刚好有同样的翻译需求,可以直接使用这个轻松又高效的服务噢!

重点笔记

Amazon Transcribe是一项自动语音识别 (ASR) 服务,让开发人员能够轻松地为其应用程序添加语音转文本功能,他可以支持多种语言的语音识别服务,其中包括英文和中国普通话的支持,而且在由光环新网运营的中国(北京)区域、由西云数据运营的中国(宁夏)区域也已支持该服务咯。

搭建简易体系架构,知识点快收藏!

示例的总体架构如下图所示:

1. 上传视频文件到 Amazon S3 存储桶,可以选定一个特定的文件夹;

2. Amazon S3监测到存储桶中某个文件夹有新增的文件,触发 lambda 函数;

3. Lambda 函数调用 Amazon Transcribe 服务,生成视频对应的文本(json格式);

4. 对字幕文本进行格式转换,生成支持播放器的字幕文件格式(srt);

5. 上传字幕文件到存储桶指定的文件夹中。


Get 轻松高效的翻译,你值得拥有~

01 创建 Amazon S3 存储桶

首先在亚马逊云科技管理控制台进入“Amazon S3”服务,点击“创建存储桶”,输入存储桶的名称,点击“创建”按钮创建一个 Amazon S3 存储桶。并且在新创建的桶里,点击“创建文件夹”,创建一个名字叫做“videos”的文件夹用于存放我们的视频文件。

注意这里我们新建一个文件夹存放需要加载字幕的视频,而不是直接把视频放到桶里,这样可以避免我们的 Lambda 函数被自己生成的字幕文件循环调用。


02 创建 IAM 角色

每个 Lambda 函数都有一个与之关联的 IAM 角色。此角色定义允许该功能与其进行交互的其他 Amazon Web Services 服务。在本示例中,您需要创建一个 IAM 角色,授予您的 Lambda 函数权限,以便与 Amazon Transcribe 服务以及在上一步中创建的 Amazon S3 服务进行交互。

在 Amazon Web Services 管理控制台中,单击“服务”,然后选择“IAM”。在左侧导航栏中选择“角色”,然后选择“创建角色”,依次选择“亚马逊云科技产品”“Lambda”作为角色类型,然后单击“下一步:权限”按钮,在“筛选策略”选择如下:

“AmazonS3FullAccess”

“ AWSLambda_FullAccess”

“ AmazonTranscribeFullAccess”

点击“下一步:审核”,在角色名称中输入“addSubtitleRole”,点击“创建角色”


03 创建 Lambda 函数

在Amazon Web Services管理控制台进入“Lambda”服务,点击“创建函数”按钮。

在“函数名称”中填写函数名称,在“运行时”的选择框中选择“Python 2.7”。这里要特别注意,我们选择更改默认执行角色,在“执行角色”中选择“使用现有角色”,然后选择刚刚创建的角色名称,点击“创建函数”按钮完成函数的创建。在此示例中,我们选择了 Python 2.7 作为开发环境,并为该 Lambda 函数赋予了上一步创建的角色。


04 配置触发条件

在 Lambda 的函数配置页面,点击“添加触发器”按钮添加触发条件。选择“S3”。

在触发条件配置页面,在“存储桶”下拉列表中选择刚刚创建的存储桶名称,在“事件类型”下拉列表中选择“Put”,在“前缀”中输入“videos/”(注意这里要有“/”),在“后缀”中输入“.mp4”,然后点击“添加”按钮,完成触发条件的添加。该触发条件设置监视刚刚创建存储桶的 videos 目录中扩展名为.mp4 的文件,如果新增一个视频,将触发该 Lambda 函数。


05 Lambda 内存和超时配置

在刚创建的 Lambda 函数中,我们需要配置了内存的大小和执行超时。由于 Lambda 函数会调用 Amazon Transcribe 服务进行文字提取,因此不需要修改内容的大小,默认值为 128MB。示例中我们采用的视频文件的时长均在半小时内,Amazon Transcribe 的处理时间通常不会超过 10 分钟,在这里我们设置超时时长“Timeout”为 10 分钟。


06 导入 Lambda 函数

打开附件中的 python 文件,将其内容粘贴在 Lambda 函数实现的区域,点击右上角的“Deploy”按钮。

Lambda 的实现主要包括以下几个步骤:

  1. 参数获取

从 event 对象中和系统变量中获取相关参数信息。

  • region:当前区域,示例中使用的是区域是宁夏区域
  • bucket_name:存储桶名称,您刚刚创建的存储桶名称
  • sourceS3Key:视频文件的key值
  • 这里是我们刚才所设置的监测videos目录下的mp4类型的文件,key值为videos/***.mp4
  • fn:根据sourceS3Key提取文件名
  • dir:根据sourceS3Key提取目录名

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)

3. 生成 srt 字幕文件

Amazon Transcribe 所抓取转化的字幕 json 数组中,包含每个字(或者词语)的开始时间、结束时间、置信度等信息。

下面我们需要把 json 数组转换成字幕文件。常见的字幕格式是 srt 格式。srt 的格式非常简单:一句时间代码 + 一句字幕。

 if (status['TranscriptionJob']['TranscriptionJobStatus']=='COMPLETED'):
        url=status['TranscriptionJob']['Transcript']['TranscriptFileUri']
        text=downloadJson(url)
        sJson = json.loads(text)
        output=process(sJson["results"]['items'])
        uploadResult(region,bucket_name,dir+'/output/'+fn, output)
    return {
        'statusCode': 200,
        'body': json.dumps('Process complete')
    }

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

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


07 测试

在管理控制台点击“S3”服务,打开刚创建的存储桶,进入“videos”目录,点击“上传”“添加文件”从本地电脑里选择一个视频文件,点击“上传”。此时就会触发我们刚刚创建的 Lambda 函数。我们可以在“Amazon Transcribe”观察 job 的执行情况。点击任何一个 job 的名称,可以显示 job 的详细信息。当 job 的状态显示为“完成”,进入到 S3 存储桶的“输出”目录,您会惊喜的发现,字幕文件已经生成了。


08 结果

下面我们看一下效果吧。看起来效果还是不错的,除了一些技术词汇可能有些偏差,大部分的对话都可以完整的听录下来。如果需要字幕内容需要翻译,这也是一个很好的起点,可以极大的降低翻译人员的工作量。


总结&成本分析

做了这么多,我们需要花费多少钱呢?亚马逊云科技官网已经贴心地为大家做了一个常用案例的成本分析啦~

按照上面的假设,Amazon Transcribe 处理一个半小时左右的网络研讨会,大概只需要人民币 4.86 元。

通过使用无服务器架构的 Amazon Transcribe,结合 Amazon Lambda 和 Amazon S3,用户可以方便的在视频处理的各种场景中,无需购买服务器,方便快速的构建自己的视频字幕转换应用。

上面的案例是一个我们在实际场景应用的简化版,适合短视频的处理。但是,在实际的运用中,由于部分视频时间较长,比如亚马逊 re:Invent 2020 的 keynote 可能长达 3-4 个小时,如果我们采用现在的架构,就会出现 Lambda 超时的问题。

对于长视频的处理,我们就需要优化架构。限于篇幅,具体的方法在本文中不再赘述,但是小伙伴们可以动起来手来,改进现在的架构!

比如把我们的 Lambda 应用分成两个部分,现在的部分仅仅用来启动 Amazon Transcribe 的任务,不再轮询去等待任务的完成。而采用 Amazon CloudWatch Event 来监听 Transcribe job 状态的变化,从而触发另一个 Lambda 处理生成的 json 格式的字幕文件转化成一个 srt 的格式,这样既可以避免超时的发生,同时也降低了 Lambda 服务轮询所产生的成本。

免责声明:文章版权归原作者所有,其内容与观点不代表Unitimes立场,亦不构成任何投资意见或建议。

计算机

1

相关文章推荐

未登录头像

暂无评论