【问题标题】:Redirecting audio output from one function to another function in python将音频输出从一个函数重定向到python中的另一个函数
【发布时间】:2023-04-06 23:18:02
【问题描述】:

假设我有两个函数来自两个不同的 API,函数 A 和 B。

默认情况下,函数 A 将音频数据输出到 wav 文件。

默认情况下,函数 B 从 wav 文件中获取音频输入并进行处理。

是否可以将数据从函数 A 流式传输到 B?如果是这样,我该怎么做?如果相关,我在 lubuntu 上工作。

这是我从 PJSUA python API 考虑的函数 A:

create_recorder(self, filename) 创建 WAV 文件记录器。

关键字参数 文件名 -- WAV 文件名

返回: WAV录音机ID

这是来自 Pocketsphinx Python API 的函数 B

decode_raw(...)

从文件中解码原始音频。 参数: fh (file) - 从中​​读取音频的文件句柄。 uttid (str) - 赋予此话语的标识符。 maxsamps (int) - 要读取的最大样本数。如果未指定或 -1,则将读取文件的其余部分。

更新:

当我尝试传递套接字或命名管道的文件名时,它会输出此错误消息,似乎 python 绑定使用的 C 函数除了 .wav 文件之外什么都不喜欢... 为什么会这样?

pjsua_aud.c .pjsua_recorder_create() 错误:无法确定 /tmp/t_fifo 的文件格式。例外:对象:LIb,操作=创建(记录器),错误=不支持选项/操作(PJ_ENOTSUP)

我需要使用 create_recorder() 返回的值,它是一个 int,用于获取 wav 记录器 id(不直接传递给 decode_raw(),而是传递给其他函数。

【问题讨论】:

  • 这取决于,你将什么传递给函数A?您传递文件名还是文件对象?如果函数 A 可以接受一个文件对象,你也许可以给它一个 StreamIO 对象。
  • 这是一个文件名......我将编辑我的原始帖子以提供更多信息。
  • 您是否尝试过使用其他名称:/tmp/t_fifo.wav 而不是 /tmp/t_fifo
  • 是的,我昨天试过了,它奏效了。我看了看 C 代码,显然它只是检查 .wav 扩展名...感谢您的帮助,现在我只是在寻找一种从 create_recorder 函数获取返回值的方法
  • 返回值在哪里使用?在decode_raw() 通话之前或之后需要它吗?如果是前者,那么流式传输将是有问题的。不要在 cmets 中为您自己的问题添加信息,edit 而是。

标签: python audio


【解决方案1】:

答案与平台高度相关,需要更多详细信息。不同的操作系统有不同的处理进程间通信或 IPC 的方式。

如果您使用的是类 UNIX 环境,则可以使用一组丰富的 IPC 原语。管道、SYS V 消息队列、共享内存、套接字等。在您的情况下,我认为使用管道或套接字是有意义的,具体取决于 A 和 B 是否在同一进程中运行。

更新:

在您的情况下,我会使用 python 的 subprocess 和或 os 模块和管道。这里的想法是为共享父进程的进程中的两个 API 创建调用上下文,该父进程还创建了一个单向命名管道并将其传递给它的子进程。然后,写入create_recorder 中的命名管道的数据将立即可用于命名管道中的 read()。

【讨论】:

  • 我认为它们在同一个进程中运行......它们肯定在同一个 python 脚本中,我没有接触过像多处理这样的花哨的东西(我不知道怎么做的)
  • 谢谢,我马上试试
  • @MaxPie: 最简单的测试——因为它可能工作——是创建一个 Unix 套接字,并将其文件名传递给create_recorder,看看它是否写入套接字,替换套接字使用常规文件,否则失败。如果它写入套接字,只需将套接字的文件描述符传递给decode_raw,就完成了。
  • 这有一个额外的属性,因为套接字是由路径定义并且全局可访问的,您不再需要在父进程中创建它,从而以很小的成本简化了实现。
  • 好的,我尝试了 unix socket 方法,但它似乎不喜欢它(create_recorder 返回一个有趣的来确定 /tmp/p_unix_socket 的文件格式,我按照这里的说明进行操作:webcache.googleusercontent.com/search?q=cache:http://…,我刚刚传递了套接字绑定到 createrecorder 的文件名,但它不起作用,我将尝试 user931794 的建议
【解决方案2】:

您可以使用命名管道 os.mkfifo() 并将函数移动到不同的线程/进程,例如:

import os
from multiprocessing import Process

os.mkfifo(filename)
try:
    Process(target=obj.create_recorder, args=[filename]).start()
    decode_raw(filename, ...)
finally:
    os.remove(filename)

【讨论】:

  • 那也没用,create_recorder 抱怨它无法识别文件名/不支持
  • @MaxPie: update your question 包含您获得的完整回溯。
  • 它只是在控制台中这样说:pjsua_aud.c .pjsua_recorder_create() 错误:无法确定 /tmp/t_fifo 的文件格式。例外:对象:LIb,操作=创建(记录器),错误=不支持选项/操作(PJ_ENOTSUP),我如何得到
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-06
  • 2021-01-29
  • 2020-10-20
  • 2022-01-04
  • 2018-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多