亚马逊AWS官方博客

利用亚马逊云科技的 AI 和媒体服务快速合成多语言视频

需求背景简介

随着全球化的发展和经济的蓬勃增长,越来越多的企业用户开始将目光投向海外市场。通过开拓海外市场,企业可以扩大市场份额,降低成本,并实现资源共享和互补。然而,在多元、复杂的全球语境中,跨语言培训成为企业开展培训业务面临的重要问题。不少企业都积累了大量的中文培训视频,如何快速、准确的为海外分支机构交付多语言的培训教材,是很多企业客户人力资源和培训部门提出的共同需求。

本文利用亚马逊云科技的一系列 AI 服务,将传统的中文培训视频和字幕,快速转换为英文视频和英文字幕,为企业的培训部门提供一种便捷的方式,降低重新制作培训教材的复杂度和成本。

系统方案架构图

主要服务和组件简介

Amazon Transcribe

Amazon Transcribe 是一种自动语音识别服务,它使用机器学习模型将音频转换为文本。您可以用 Amazon Transcribe 作独立的转录服务,也可以向任何应用程序添加 speech-to-text 功能。Amazon Transcribe 使用户可以轻松地在媒体内容中添加字幕,而无需事先的机器学习经验。

Amazon Transcribe 支持 WebVTT (*.vtt) 和 SubRip (*.srt) 格式输出用作视频字幕。设置批量视频转录作业时,您可以选择一种或两种文件类型。使用字幕功能时,将生成您选择的字幕文件和常规脚本文件(包含其他信息)。字幕和转录文件输出到同一个目的地。

Amazon Translate

Amazon Translate 是一项神经网络机器翻译服务,使用先进的机器学习技术按需提供快速、高质量的翻译。神经网络机器翻译是一种语言翻译自动化形式,采用深度学习模型,可以提供比基于规则的传统统计式翻译算法更准确、更自然的翻译。

Amazon Translate 支持对面向不同用户的网站和应用程序的内容进行本地化,可轻松翻译大量文本以进行分析,也可以高效实现用户间跨语言交流。

Amazon Polly

Amazon Polly 是一项将文本转换为逼真语音的服务,包括许多神经网络语音合成(NTTS)语音,通过一种新的机器学习方法,在语音质量方面实现了突破性的改进,从而为客户提供了最自然、最人性化的文本到语音。神经网络语音合成技术还支持根据新闻叙述用例定制的 Newcaster 演讲风格。

Amazon Polly 可以提供几十种逼真的语音并支持多种语言,因此您可以选择最合适的语音,并在许多地理位置发布具有语音功能的应用程序。Amazon Polly 简单易用 – 您只需将要转换为语音的文本发送到 Amazon Polly API,Amazon Polly 便会立即将音频流返回到您的应用程序。您可以直接播放该音频流,也可将其存储为 MP3 等标准音频文件格式。Amazon Polly 支持语音合成标记语言(SSML)标签(如 prosody),因此您可以调整语速、音调或音量。

AWS Elemental MediaConvert

AWS Elemental MediaConvert 是一项基于文件的视频处理服务,允许使用任何大小内容库的视频提供商轻松可靠地对点播内容进行转码,以便实现在广播和多屏交付。AWS Elemental MediaConvert 可以作为单独的服务使用,也可以与其他 AWS Media Services 集成,从而让您构建基于文件的灵活视频工作流,同时全面控制视频质量和可预测的按需付费账单。

AWS Elemental MediaConvert 支持大量视频输入和输出格式,包括适用于广播的格式以及通过 Internet 交付的格式。该服务支持 AVC、HEVC、AV1、Apple ProRes 和 MPEG-2 压缩标准,包括支持高级色彩采样(10 位 4:2:2)。它支持广泛的自适应比特率打包格式,包括 CMAF、Apple HLS、DASH ISO 和 Microsoft Smooth Streaming。AWS Elemental MediaConvert 还支持处理和转换 4K 和 8K 分辨率来源和高动态范围(HDR)视频内容(包括杜比视界)。

在视频处理工作流中,基于文件的视频转码解决方案处理视频文件,创建原始内容的压缩版本,以减小其大小、更改其格式或提高播放设备的兼容性。基于文件的视频转码解决方案可以转换任何视频输入源,从高质量的演播室主控到在移动设备上捕获的视频,并生成可分发给观众的内容。

部署步骤

亚马逊云科技的上述服务,都可以通过在管理控制台页面手工运行任务完成,为了简化操作步骤,减少人工操作可能出现的错误,本方案采用 Lambda 和 EventBridge 等服务进行自动化操作,本文所有的 Lambda 函数代码均可基于 python 3.11 和 arm64 架构进行部署。

注意如果部署在自己的环境,本文中的 S3 Bucket 名称‘media’需要更改为自己的 Bucket。

根据架构图和处理流程,分为以下几个环节:

1. 自动识别视频中的中文语音并生成中文字幕格式文件

创建 lambda function,命名为“media_transcribe”,函数代码如下:

import json
import boto3
def lambda_handler(event, context):    
    #获取S3文件属性
    filename = event['Records'][0]['s3']['object']['key']
    if '/' in filename:
        return #如果文件不在根目录下则不进行识别
    fileuri = 's3://media/' + filename,
    #创建Transcribe任务
    transcribe_client = boto3.client('transcribe')
    response = transcribe_client.start_transcription_job(
        TranscriptionJobName = filename.strip('.mp4') + '-zh_CN',
        LanguageCode = 'zh-CN',
        MediaFormat = 'mp4',
        Media = {
            'MediaFileUri': str(fileuri[0])
        },
        OutputBucketName = 'media',
        OutputKey = filename.strip('.mp4') + '-zh_CN/',
        Subtitles={
            'Formats': [
                'srt','vtt'
            ]
        }
    )
    return {
        'result': 'transcribe job created'
}

为运行此函数的 IAM Role 赋予访问 Transcribe 服务和 S3 的权限,为了简化操作,本文使用托管的 AmazonTranscribeFullAccess 和 AmazonS3FullAccess 两个 Policy。Transcribe 是异步任务,不需要为 Lambda 延长运行时间,保留默认值即可运行。

2. 翻译上一步生成的中文字幕格式文件,转换为英文字幕格式文件

创建 Lambda function,命名为“media_translate”,函数代码如下:

import json
import boto3
def lambda_handler(event, context):
    jobname = event['detail']['TranscriptionJobName']
    if jobname[-6:] != '-zh_CN':
        return #避免重复翻译新生成的字幕,如果jobname结尾不是-zh_CN,就不需要执行翻译
    #创建Translate Job
    translate_client = boto3.client('translate')
    response = translate_client.start_text_translation_job(
        JobName = jobname,
        InputDataConfig = {
            'S3Uri' : 's3://media/' + jobname + '/',
            'ContentType' : 'text/plain'
        },
        OutputDataConfig = {
            'S3Uri' : 's3://media/' + jobname.strip('-zh_CN') + '-en/',
        },
        DataAccessRoleArn = 'arn:aws:iam::096454897560:role/service-role/AmazonTranslateServiceRole-translate-s3', #运行Translate服务的Role,替换为自己的IAMRole ARN,这个Role需要具有访问S3的权限
        SourceLanguageCode = 'zh',
        TargetLanguageCodes = ['en']
    )
    return {
         'result': 'translate job created'
    }

为运行此函数的 IAM Role 赋予访问 Translate 服务和 IAM PassRole 的权限,为了简化操作,本文使用托管的 TranslateFullAccess 和 IAMFullAccess 两个 Policy。Translate 同样是异步任务,不需要为 Lambda 延长运行时间,保留默认值即可运行。

Translate 任务执行时间较长,一般需要 15 分钟以上。可以在 Translate 服务管理控制台查看任务运行的状态。

3. 转换英文字幕格式文件为可阅读的英文文本,并通过 Amazon Polly 生成语音文件

创建 Lambda function,命名为“media_text2speech”,函数代码如下:

import json
import boto3
import os
def lambda_handler(event, context):
    jobid = event['detail']['jobId']
    #获取Translate Job结果
    translate_client = boto3.client('translate')
    response = translate_client.describe_text_translation_job(JobId = jobid)
    jobname = response['TextTranslationJobProperties']['JobName']
    folder = response['TextTranslationJobProperties']['OutputDataConfig']['S3Uri']
    #获取转换后的srt文件
    en_srtfile = folder + 'en.' + jobname + '.srt'
    s3_client = boto3.client('s3')
    tmpfile = '/tmp/speech.srt'
    s3_client.download_file('media', en_srtfile.split('media/')[1], tmpfile)
    #解析转换后的srt文件
    targetfile =  open('/tmp/target.txt', 'w')
    with open (tmpfile, 'r') as file:
        line = file.readline()
        linenum = 1
        while line:
            if (linenum + 1)%4 == 0:
                targetfile.write(line)
            line = file.readline()
            linenum = linenum +1
    targetfile.write('\n')
    file.close()
    targetfile.close()    
    #生成音频文件
    file = open('/tmp/target.txt', 'r')
    voice_content = file.read()
    polly_client = boto3.client('polly')
    response = polly_client.start_speech_synthesis_task(
        Engine = 'neural',
        LanguageCode = 'es-US',
        OutputFormat = 'mp3',
        OutputS3BucketName = 'media',
        OutputS3KeyPrefix = jobname.strip('-zh_CN') + '-voice/',
        #SnsTopicArn='string',
        Text = voice_content,
        TextType = 'text',
        VoiceId='Joanna'
    )
    file.close()
    return {
        'result': ‘polly job created’
    }

为运行此函数的 IAM Role 赋予访问 Translate 服务、Polly 服务和 S3 的权限,为了简化操作,本文使用托管的 TranslateReadOnly、AmazonPollyFullAccess 和 AmazonS3FullAccess 这三个 Policy。

虽然 Amazon Polly 同样是异步任务,但此函数需要把字幕文件下载到 Lambda 的临时储存空间进行处理,需要花一些时间,因此建议把 Lambda 超时时间由默认的 3 秒钟修改为 1 分钟。

4. 为英文语音文件生成新的英文字幕格式文件

创建 Lambda function,命名为“media_makecaptions”,函数代码如下:

import json
import boto3
def lambda_handler(event, context):
    #获取S3文件属性
    filename = event['Records'][0]['s3']['object']['key']
    fileuri = 's3://media/' + filename,    
    #创建Transcribe任务
    transcribe_client = boto3.client('transcribe')
    response = transcribe_client.start_transcription_job(
        TranscriptionJobName = filename.split('/')[1].strip('.').strip('.mp3'),
        #IdentifyLanguage = True,
        LanguageCode = 'en-US',
        MediaFormat = 'mp3',
        Media = {
            'MediaFileUri': str(fileuri[0])
        },
        OutputBucketName = 'media',
        OutputKey = filename.split('/')[0] + '/',
        Subtitles={
            'Formats': [
                'srt','vtt'
            ]
        }
    )    
    return {
        'result': ‘transcribe job created'
    }

为运行此函数的 IAM Role 赋予访问 Transcribe 服务和 S3 的权限,为了简化操作,本文使用托管的 AmazonTranscribeFullAccess 和 AmazonS3FullAccess 两个 Policy。Transcribe 是异步任务,不需要为 Lambda 延长运行时间,保留默认值即可运行。

5. 为每个 Lambda 函数配置触发条件

前面的步骤一共创建完成 4 个 Lambda 函数,可以在 Lambda 的管理控制台看到下列函数:

下面按照处理流程分别为每个函数配置触发条件:

1)media_transcribe

在 S3 桶的属性中,配置当存储桶中创建 mp4 文件时,触发 media_transcribe 函数

2)media_translate

在 EventBridge 中,创建规则,当发生 Transcribe Job State Change 为“COMPLETED”事件时,触发 media_translate 函数

3)media_text2speech

在 EventBridge 中,创建规则,当发生 Translate TextTranslation Job State Change 为“COMPLETED”事件时,触发 media_text2speech 函数

4)media_makecaptions

在 S3 桶的属性中,配置当存储桶中创建 mp3 文件时,触发 media_makecaptions 函数

6. 在存储桶中上传一个 mp4 视频文件进行验证,依次检查相关服务中的任务,可以看到所有任务都可以自动完成而无需人工干预。

S3 桶中上传文件:

Transcribe 任务:

Translate 任务:

Amazon Polly 任务:

media_makecaptions 任务:

在 S3 桶中,找到生成的 3 个相关文件,分别是原始 mp4 视频文件、英文语音的 mp3 文件和英文字幕格式文件。

其中原始 mp4 文件在桶的根目录中,另外两个英文文件在以-voice 结尾的目录中。

7. 用英文语音和英文字幕合成视频

在真实的业务环境中,建议对生成的字幕文件仍然通过人工进行内容的二次校准和时间戳修正,因此本文不采用自动化任务进行合成,而是通过 AWS 管理控制台进行视频合成的操作。

打开 AWS Elemental MediaConvert 的控制台页面,在 Jobs 页面中,点击橙色的“Create Job”按钮创建任务。

在任务界面的 Input 1 区段中输入原始视频文件的 S3 URI,这里会采集需要合成的视频内容。

在 Audio selector 1 区段中,点击打开“External file”,输入英文语音 mp3 文件的 S3 URI,这里会采集需要合成的音频内容。

在 Caption Selectors 区段中,点击“Add captions selector”按钮,在 Caption Selector 1 中,Source 选择 WebVTT,WebVTT Source 选择 External file,Source file 填写 VTT 字幕文件的 S3 URI,这里会采集需要合成的字幕内容。

返回页面上方,点击左面 Output groups 旁边的“Add”按钮增加视频输出目标,在弹出的窗口选择“File Group”。

在输出的 File group setting 中,Destination 填写 S3 桶的名字。

点击左边的 H.264,ACC 配置输出,在 Video 区段中,最高码率 Max bitrate (bit/s)填写 4096000。

点击“Add caption Pro”按钮,增加字幕配置,Caption source 选择“Caption Selector 1”,Destination type 选择“Burn-in”烧录进 mp4 文件,下面的 Pass style information 选择“Enabled”,点击 Create 创建合成任务。

等待任务完成后,就可以在 File group 输出的 S3 桶中找到新创建的 mp4 文件,下载 mp4 文件,用播放器播放,可以看到已经在原来的视频中,增加了英文字幕,同时视频文件的声音也变成了英文解说。

小结

本文简单介绍了利用亚马逊云科技的 AI 服务,快速对中文视频进行英文转换的一种便捷方式,读者如果有兴趣,可以自行修改 Lambda 代码中的 LanguageCode 尝试更改为其他语言,例如将英文视频转换为中文视频。

同时,亚马逊云科技也提供了一个带有前端界面的为视频生成多语言字幕的解决方案,可以参考 https://awslabs.github.io/aws-video-transcriber/zh/

本篇作者

王华

亚马逊云科技解决方案架构师。有 20 年从事软件架构、应用开发、系统集成等工作经验。擅长 Web 领域应用系统架构设计和开发运维,即时通讯软件、UC、企业 IT 服务台和云呼叫中心系统的开发部署工作,从事过多个大型企业呼叫中心项目的设计、开发与部署。目前专注于制造业和呼叫中心领域的研究和方案推广。