如何使用 Python 将语音记录转成文本


原文地址:如何使用 Python 将语音记录转成文本

本篇文章分享了如何使用 Python 将语音记录转录成文本,其中我们要使用AssemblyAI 来做语音转成文本。

当您有一个或多个人谈话的录音时,有一种高度准确和自动化的方式将口语提取为文本是很有用的。获得文本后,您可以将其用于进一步分析或用作辅助功能。

在本教程中,我们将使用称为AssemblyAI 的高精度语音到文本 Web 应用程序编程接口从 MP3 录音(也支持许多其他格式)中提取文本。

使用本教程中的代码,您将能够获取包含语音的音频文件, 例如我录制的示例, 并输出如下所示的高度准确的文本转录:

An object relational mapper is a code library that automates the transfer of 
data stored in relational, databases into objects that are more commonly used
in application code or EMS are useful because they provide a high level 
abstraction upon a relational database that allows developers to write Python 
code instead of sequel to create read update and delete, data and schemas in 
their database. Developers can use the programming language. They are 
comfortable with to work with a database instead of writing SQL...

(the text goes on from here but I abbreviated it at this point)

教程要求

在本教程中,我们将使用以下依赖项,我们将在稍后安装它们。确保您的环境中还安装了 Python 3, 最好安装了 3.6 或更新版本

我们将使用以下依赖项来完成本教程:

  • 请求 2.24.0 版AssemblyAI语音转文本 API发出 HTTP 请求
  • 一个AssemblyAI帐户,您可以在此处注册一个 免费的 API 访问密钥

这篇博文中的所有代码都可以在 MIT 许可下在 GitHub 上的 blog-code-examples 存储库的transcribe-speech-text-script 目录下开源 。根据需要为自己的项目使用源代码。

设置开发环境

切换到保存 Python虚拟环境的目录 。我将我的保存在venvs用户主目录中命名的子目录中。使用以下命令为此项目创建一个新的 virtualenv。

python3 -m venv ~/venvs/pytranscribe

使用activateshell 脚本激活 virtualenv :

source ~/venvs/pytranscribe/bin/activate

执行上述命令后,命令提示符将更改,以便将 virtualenv 的名称添加到原始命令提示符格式之前,因此如果您的提示符只是 $,则现在看起来如下所示:

pip install requests==2.24.0

查找类似于以下内容的输出,以确认从 PyPI 正确安装了适当的包。

(pytranscribe) $ pip install requests==2.24.0
Collecting requests==2.24.0
  Using cached https://files.pythonhosted.org/packages/45/1e/0c169c6a5381e241ba7404532c16a21d86ab872c9bed8bdcd4c423954103/requests-2.24.0-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests==2.24.0)
  Using cached https://files.pythonhosted.org/packages/5e/c4/6c4fe722df5343c33226f0b4e0bb042e4dc13483228b4718baf286f86d87/certifi-2020.6.20-py2.py3-none-any.whl
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests==2.24.0)
  Using cached https://files.pythonhosted.org/packages/9f/f0/a391d1463ebb1b233795cabfc0ef38d3db4442339de68f847026199e69d7/urllib3-1.25.10-py2.py3-none-any.whl
Collecting chardet<4,>=3.0.2 (from requests==2.24.0)
  Using cached https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl
Collecting idna<3,>=2.5 (from requests==2.24.0)
  Using cached https://files.pythonhosted.org/packages/a2/38/928ddce2273eaa564f6f50de919327bf3a00f091b5baba8dfa9460f3a8a8/idna-2.10-py2.py3-none-any.whl
Installing collected packages: certifi, urllib3, chardet, idna, requests
Successfully installed certifi-2020.6.20 chardet-3.0.4 idna-2.10 requests-2.24.0 urllib3-1.25.10

我们已经安装了所有必需的依赖项,因此我们可以开始编写应用程序。

上传、启动和转录音频

我们拥有开始构建将音频转录为文本的应用程序所需的一切。我们将在三个文件中构建这个应用程序:

  1. upload_audio_file.py:将您的音频文件上传到 AssemblyAI 服务上的安全位置,以便可以对其进行处理。如果您的音频文件已经可以通过公共 URL 访问,则无需执行此步骤,只需按照 此快速入门即可
  2. initial_transcription.py:告诉 API 要转录哪个文件并立即开始
  3. get_transcription.py : 如果仍在处理,则打印转录的状态,或在处理完成时显示转录的结果

创建一个名为的新目录,pytranscribe用于在我们编写这些文件时存储这些文件。然后切换到新的项目目录。

mkdir pytranscribe 
cd pytranscribe

我们还需要将我们的 AssemblyAI API 密钥导出为环境变量。 注册一个 AssemblyAI 帐户 并登录到 AssemblyAI 仪表板,然后复制“您的 API 令牌”,如下面的屏幕截图所示:

如何使用 Python 将语音记录转成文本

export  ASSEMBLYAI_KEY = your-api-key-here

请注意,您必须export在希望此密钥可访问的每个命令行窗口中使用该命令。如果您没有ASSEMBLYAI_KEY在运行脚本的环境中导出令牌,我们正在编写的脚本将无法访问 API 。

现在我们已经创建了项目目录并将 API 密钥设置为环境变量,让我们继续编写第一个文件的代码,该文件将音频文件上传到 AssemblyAI 服务。

上传音频文件进行转录

创建一个名为的新文件并将upload_audio_file.py以下代码放入其中:

import argparse
import os
import requests


API_URL = "https://api.assemblyai.com/v2/"


def upload_file_to_api(filename):
    """Checks for a valid file and then uploads it to AssemblyAI
    so it can be saved to a secure URL that only that service can access.
    When the upload is complete we can then initiate the transcription
    API call.
    Returns the API JSON if successful, or None if file does not exist.
    """
    if not os.path.exists(filename):
        return None

    def read_file(filename, chunk_size=5242880):
        with open(filename, 'rb') as _file:
            while True:
                data = _file.read(chunk_size)
                if not data:
                    break
                yield data

    headers = {'authorization': os.getenv("ASSEMBLYAI_KEY")}
    response = requests.post("".join([API_URL, "upload"]), headers=headers,
                             data=read_file(filename))
    return response.json()

上面的代码导入argparse,osrequests包,以便我们可以在此脚本中使用它们。该API_URL是具有AssemblyAI服务的基本URL恒定。我们upload_file_to_api使用单个参数定义 函数,该参数filename 应该是一个带有文件绝对路径及其文件名的字符串。

在函数中,我们检查文件是否存在,然后使用 Request 的 分块传输编码 将大文件流式传输到 AssemblyAI API。

os模块的getenv函数使用export带有getenv. 确保export在运行此脚本的终端中使用该命令,否则该ASSEMBLYAI_KEY值将为空。如有疑问,请使用echo $ASSEMBLY_AI以查看该值是否与您的 API 密钥匹配。

要使用该upload_file_to_api函数,请在upload_audio_file.py文件中添加以下代码行,以便我们可以正确地将此代码作为使用python命令调用的脚本执行:

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("filename")
    args = parser.parse_args()
    upload_filename = args.filename
    response_json = upload_file_to_api(upload_filename)
    if not response_json:
        print("file does not exist")
    else:
        print("File uploaded to URL: {}".format(response_json['upload_url']))

上面的代码创建了一个ArgumentParser对象,该对象允许应用程序从命令行获取单个参数来指定我们要访问、读取和上传到 AssmeblyAI 服务的文件。

如果文件不存在,脚本将打印一条消息,指出找不到文件。在我们在该路径找到正确文件的快乐路径中,然后使用upload_file_to_api函数中的代码上传文件。

upload_audio_file.py通过使用命令在命令行上运行它来执行完成的脚本python。替换FULL_PATH_TO_FILE 为您要上传的文件的绝对路径,例如 /Users/matt/devel/audio.mp3.

python upload_audio_file.py FULL_PATH_TO_FILE

假设在您指定的位置找到该文件,当脚本完成上传文件时,它会打印一条具有唯一 URL 的消息,如下所示:

File uploaded to URL: https://cdn.assemblyai.com/upload/463ce27f-0922-4ea9-9ce4-3353d84b5638

此 URL 不公开,只能由 AssemblyAI 服务使用,因此除了您和他们的转录 API 之外,没有其他人能够访问您的文件及其内容。

重要的部分是 URL 的最后一部分,在本例中是463ce27f-0922-4ea9-9ce4-3353d84b5638. 保存该唯一标识符,因为我们需要将其传递到启动转录服务的下一个脚本中。

启动转录

接下来,我们将编写一些代码来启动转录。创建一个名为initiate_transcription.py. 将以下代码添加到新文件中。

import argparse
import os
import requests


API_URL = "https://api.assemblyai.com/v2/"
CDN_URL = "https://cdn.assemblyai.com/"


def initiate_transcription(file_id):
    """Sends a request to the API to transcribe a specific
    file that was previously uploaded to the API. This will
    not immediately return the transcription because it takes
    a moment for the service to analyze and perform the
    transcription, so there is a different function to retrieve
    the results.
    """
    endpoint = "".join([API_URL, "transcript"])
    json = {"audio_url": "".join([CDN_URL, "upload/{}".format(file_id)])}
    headers = {
        "authorization": os.getenv("ASSEMBLYAI_KEY"),
        "content-type": "application/json"
    }
    response = requests.post(endpoint, json=json, headers=headers)
    return response.json()

我们具有与之前脚本相同的导入,并且我们添加了一个新常量,CDN_URL它与 AssemblyAI 存储上传音频文件的单独 URL 相匹配。

initiate_transcription函数本质上只是向 AssemblyAI API 设置一个 HTTP 请求,以在传入的特定 URL 处开始对音频文件的转录过程。这就是为什么传入file_id很重要:完成了我们的音频文件的 URL告诉 AssemblyAI 检索。

通过附加此代码来完成文件,以便可以轻松地从带有参数的命令行调用它。

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("file_id")
    args = parser.parse_args()
    file_id = args.file_id
    response_json = initiate_transcription(file_id)
    print(response_json)

通过pythoninitiate_transcription文件上运行命令来 启动脚本,并传入您在上一步中保存的唯一文件标识符。

# the FILE_IDENTIFIER is returned in the previous step and will
# look something like this: 463ce27f-0922-4ea9-9ce4-3353d84b5638
python initiate_transcription.py FILE_IDENTIFIER

API 将发回此脚本打印到命令行的 JSON 响应。

{'audio_end_at': None, 'acoustic_model': 'assemblyai_default', 'text': None, 
 'audio_url': 'https://cdn.assemblyai.com/upload/463ce27f-0922-4ea9-9ce4-3353d84b5638', 
 'speed_boost': False, 'language_model': 'assemblyai_default', 'redact_pii': False, 
 'confidence': None, 'webhook_status_code': None, 
 'id': 'gkuu2krb1-8c7f-4fe3-bb69-6b14a2cac067', 'status': 'queued', 'boost_param': None, 
 'words': None, 'format_text': True, 'webhook_url': None, 'punctuate': True, 
 'utterances': None, 'audio_duration': None, 'auto_highlights': False, 
 'word_boost': [], 'dual_channel': None, 'audio_start_from': None}

记下idJSON 响应中键的值。这是我们需要用来检索转录结果的转录标识符。在这个例子中,它是gkuu2krb1-8c7f-4fe3-bb69-6b14a2cac067。在您自己的回复中复制转录标识符,因为我们将需要它来检查下一步转录过程何时完成。

检索转录结果

我们已经上传并开始转录过程,所以让我们尽快得到结果。

返回结果所需的时间取决于文件的大小,因此下一个脚本将向 API 发送 HTTP 请求并报告转录状态,或者在完成时打印输出。

创建第三个名为的 Python 文件并将get_transcription.py以下代码放入其中。

import argparse
import os
import requests


API_URL = "https://api.assemblyai.com/v2/"


def get_transcription(transcription_id):
    """Requests the transcription from the API and returns the JSON
    response."""
    endpoint = "".join([API_URL, "transcript/{}".format(transcription_id)])
    headers = {"authorization": os.getenv('ASSEMBLYAI_KEY')}
    response = requests.get(endpoint, headers=headers)
    return response.json()


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("transcription_id")
    args = parser.parse_args()
    transcription_id = args.transcription_id
    response_json = get_transcription(transcription_id)
    if response_json['status'] == "completed":
        for word in response_json['words']:
            print(word['text'], end=" ")
    else:
        print("current status of transcription request: {}".format(
              response_json['status']))

上面的代码与其他脚本具有相同的导入。在这个新get_transcription函数中,我们只需使用我们的 API 密钥和上一步中的转录标识符(而不是文件标识符)调用 AssemblyAI API 。我们检索 JSON 响应并返回它。

在主函数中,我们处理作为命令行参数传入的转录标识符并将其传递给 get_transcription函数。如果来自get_transcription函数的响应 JSON 包含completed状态,那么我们将打印转录结果。否则,打印当前状态,它是queuedprocessing之前completed

使用命令行和上一节中的转录标识符调用脚本:

python get_transcription.py TRANSCRIPTION_ID

如果服务还没有开始处理成绩单,那么它会queued像这样返回:

current status of transcription request: queued

当服务当前正在处理音频文件时,它将返回processing

current status of transcription request: processing

当服务当前正在处理音频文件时,它将返回processing

current status of transcription request: processing

该过程完成后,我们的脚本将返回转录文本,如下所示:

An object relational mapper is a code library that automates the transfer of 
data stored in relational, databases into objects that are more commonly used
in application code or EMS are useful because they provide a high level 

...(output abbreviated)

完成! 

评论

登录后评论

服务器优惠活动

Top