【问题标题】:downloading multiple audio files in a loop failed (python)循环下载多个音频文件失败(python)
【发布时间】:2021-07-01 07:17:11
【问题描述】:

我正在尝试使用 python 中的循环从 AWS polly(文本到语音服务)下载 mp3 文件 我使用的代码如下:

for i in range(0, 3):
    filename = str(i) + ".mp3"
    response = polly_client.synthesize_speech(VoiceId='Joanna',
                OutputFormat='mp3', 
                Text = "blah blah blah"
    file = open(filename, 'wb')
    file.write(response['AudioStream'].read())
    file.close()

这最终给了我 1kb 的文件,这意味着每个文件中没有任何内容.. 我可以做些什么来改进代码,以便循环暂停,直到每个音频文件都下载完成..

提前谢谢你。

【问题讨论】:

  • 如果您在任何循环之外对单个文件执行此操作,是否可以按预期工作?
  • 是的,它工作正常
  • 我相信我需要使用子进程...但我不知道如何..
  • 嗯,我认为你不需要subprocess。我没有 AWS 凭证,否则我会自己尝试,但仅从查看文档来看,response["AudioStream"] 是一个 botocore.response.StreamingBody 对象,它代表一个实时的异步套接字连接,数据可以通过该连接流式传输。您的循环运行得如此之快,以至于一旦有机会首先开始读取,套接字实际上就关闭了。似乎存在这些特殊的 waiter 对象,它们等待异步进程 - 不确定它们是如何工作的,但值得研究。
  • 您还可以为synthesize_speech 方法设置自定义InvocationType 关键字参数。将其从Event 更改为RequestResponse 具有将一些异步函数更改为同步函数的效果,但同样,我对AWS 了解不多。

标签: python loops amazon amazon-polly


【解决方案1】:

我找到了解决这个问题的方法,但方式有点不同..

正如我所猜测的,使用子进程函数可能是关键..

在子进程中使用命令(aws 命令行)可生成良好的 mp3 文件。

代码如下

import pandas as pd
import subprocess
import codecs

for i in range (0,3):
    word = 'blah blah blah'
    file_name = '0' + str(i) + '.mp3'
    print(word)
    
    command = 'aws polly synthesize-speech --text-type ssml --output-format "mp3" --voice-id "Salli" --text "<speak>' + word + '</speak>" ' + file_name
    print(command)
    

        
    subprocess.call(command, shell=True)

【讨论】:

    【解决方案2】:

    看看这个来自亚马逊的example。它演示了使用with closing(...) 来确保正确关闭响应流。

    这里有一些代码,未经测试,应该适合你:

    from contextlib import closing
    
    for i in range(3):
        filename = f'{i}.mp3'
        response = polly_client.synthesize_speech(VoiceId='Joanna',
                    OutputFormat='mp3', 
                    Text = "blah blah blah"
        if 'AudioStream' in response:
            with closing(response['AudioStream']) as stream, open(filename, 'wb') as file:
                while data := stream.read():
                    file.write(data)
        else:
            print(f'Problem streaming audio: {response=}')
    

    【讨论】:

    • 不幸的是,这也不起作用..这种情况导致所有三个文件都是 0kb。
    • 但是,我找到了另一种方法。我使用命令和子进程而不是直接在 Python 中处理它。它有效。不过感谢您的帮助。
    • @JohnLee:我认为您应该进一步探索文档。使用 subprocess 不是处理文件的好方法。问题基本上是您的代码没有读取完成返回的流 - 单个读取操作可能只会导致 1K 的数据。您应该遍历流,直到读取 0 个字节。
    • @JohnLee:我已经更新了我的答案以循环流数据直到它被关闭。
    猜你喜欢
    • 1970-01-01
    • 2020-09-13
    • 2017-05-11
    • 2017-08-19
    • 2019-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多