【问题标题】:Record voice coming of a certain PID Ubuntu录制某个PID Ubuntu的声音
【发布时间】:2021-06-28 13:13:27
【问题描述】:

我正在研究文本到语音的算法,我终于成功了,这个算法所做的就是转成一个 html 文件

进入演讲,像这样:python record.py file.html

在这里一切都很好,但我想使用这个命令在多个文件上运行相同的命令:

python record.py file1.html & python record.py file2.html & python record.py file3.html

但不是单独录制每个音频,而是在输出上得到重叠。

PS1:我使用的是 ubuntu 服务器,我想在超过 6000 个文件上运行我的命令,每个文件大约需要 20 分钟,因为它们是一个大文件。

PS2:我正在使用 pyaudio 录制声音,这是我代码中的录制部分:

from seleniumwire import webdriver
import sys
from webdriver_manager.chrome import ChromeDriverManager
import time
import pyaudio
import wave
from selenium.webdriver.chrome.options import Options
import warnings

warnings.simplefilter(action='ignore', category=FutureWarning)
chrome_options = Options()
chrome_options.add_argument("--headless")


browser = webdriver.Chrome(ChromeDriverManager().install(), chrome_options=chrome_options)
#selenium part 
browser.get('website')
search = browser.find_element_by_id("text-area")
search.clear()
data="this is a simple test"
search.send_keys(data)
time.sleep(2)
browser.find_element_by_id("btn").click()
print("waiting for audio")
size = len(data)/200
time.sleep(size*2)
print("audio detected")
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
#number = len(data)
RECORD_SECONDS = size*17
WAVE_OUTPUT_FILENAME = 'first.mp3'
open(WAVE_OUTPUT_FILENAME, "wb+")
frames = []

p = pyaudio.PyAudio()

stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE,input=True, frames_per_buffer=CHUNK)

print("started recording")
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    audio = stream.read(CHUNK)
    frames.append(audio)

print("end of recording")
stream.stop_stream()
stream.close()
p.terminate()

wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()

有没有办法记录来自某个 PID 的音频。

我听说过 docker 容器,但我不知道它在这种情况下是否有帮助。

【问题讨论】:

  • 您是否正在使用一个&,因为您想并行执行它们?如果你改为使用&& 会发生什么?那应该一次执行一个命令。可能会帮助您确定这是并行处理问题还是其他问题。
  • && 会及时记录一次,它工作正常,但在我的情况下,完成工作需要 80 多天,所以根本不是一个可行的解决方案,我想并行运行它们
  • 您可以编辑您的代码以包含最小的可重现示例吗?具体来说,您使用什么imports,专门处理输入文件名的代码在哪里?我正在尝试运行您的代码,但如前所述,您似乎打开了与文件名无关的相同流。
  • 我已经添加了我可以添加的信息,所以这个文件会运行多次,当然每次调用都会更改文件名。
  • 我看到了几件事。我没有看到输入文件名变量在任何地方使用,只有输出文件first.mp3。看起来也有一些不必要的代码(为什么要根据随机字符串的大小来休眠?,重现这个问题需要底部的硒部分还是波部分?)。

标签: python ubuntu pyaudio pulseaudio


【解决方案1】:

我无法让您的示例代码工作,但我有一个基本猜想:您是否更改了每个调用的输出文件名?查看您的脚本,情况似乎并非如此。在某些情况下,不更改文件名可能会导致乱码。

某些包(例如pyttsx3)会做一些时髦的事情,以便将音频写入非线程安全的文件。这很可能是您的方法所发生的情况。

离线文字转语音

我发现完成这项任务的一种非常可靠的方法是直接调用espeak 之类的东西。

I've written a little package that provides a CLI for this.它的核心在这个sn-p:

import os
import tempfile
import re

# These packages are conveniences.
# Listing builtin packages that will require a few more lines to use
from bs4 import BeautifulSoup  # Alt. html.parser


def text_to_mp3(text: str, outfile: str) -> None:
    """Given some text, generate an mp3 speaking the text.
    Args:
        text (str): Text to speak
        outfile (str): *.mp3 file to write
    """

    # For some reason espeak doesn't find NamedTemporaryFile files to be agreeable...
    _, text_filename = tempfile.mkstemp(suffix=".txt")

    with open(text_filename, "w") as file:
        file.write(text)
    try:
        with tempfile.NamedTemporaryFile(suffix=".wav", delete=True) as wav_file:
            os.system(f"espeak -f {text_filename} -w {wav_file.name}")
            os.system(f"lame --preset insane {wav_file.name} {outfile} --silent")
    finally:
        if os.path.exists(text_filename):
            os.remove(text_filename)


def html_to_mp3(html: str, outfile: str, select: str = "body") -> None:
    """Given a string containing html, generate an *.mp3 that speaks the text.
    Args:
        html (str): HTML string
        outfile (str): *.mp3 to generate
        select (str, optional): CSS selector from which to select text. Defaults to "body".
    Raises:
        ValueError: In case the CSS selector is not present in the text.
    """
    soup = BeautifulSoup(html, features="html.parser")
    elements = soup.select(select)
    if not elements:
        raise ValueError(f"No elements found for CSS selector `{select}`")
    text = "\n".join([element.get_text() for element in elements])
    text_to_mp3(text, outfile)

基本步骤是:

  1. 使用 beautifulsoup 从 html 文件中提取感兴趣的文本
  2. 在感兴趣的文本上调用espeak,并将结果输出到*.wav 文件。
    • 我们将文本写入文件,而不是尝试通过命令传递一个大字符串,以便回避解析 '" 等问题。
    • espeak 只输出到wav
    • 语音有很多选项可供修改
  3. 使用lame 将上一步中的*.wav 转换为mp3。

虽然您可能已经在您的计算机上安装了这些实用程序,但您始终可以通过以下方式安装它们(在 ubuntu 上):

sudo apt-get update
sudo apt-get install lame espeak

在线文字转语音

如果您可以使用连接到 google 的在线文本转语音,那么 gTTS 包的效果很好。特别是,以下内容可按您的意愿工作:

gtts-cli 'hello' --output hello.mp3 & gtts-cli 'world' --output world.mp3

【讨论】:

  • 感谢您的努力,您为我提供了一个替代方案,但实际上并没有解决我的问题,我想要的是运行一个只能记录某个程序的 pyaudio 脚本(例如:google chrome)不是麦克风的全部输出
【解决方案2】:

我解决的方法是从网站下载音频文件,而不是

记录下来,link 帮了大忙。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-07
    • 2011-06-17
    • 1970-01-01
    相关资源
    最近更新 更多