在 Python 中管道 SoX - 子流程替代方案?

Posted

技术标签:

【中文标题】在 Python 中管道 SoX - 子流程替代方案?【英文标题】:Piping SoX in Python - subprocess alternative? 【发布时间】:2012-10-21 15:43:48 【问题描述】:

我在应用程序中使用SoX。应用程序使用它对音频文件进行各种操作,例如修剪。

这很好用:

from subprocess import Popen, PIPE

kwargs = 'stdin': PIPE, 'stdout': PIPE, 'stderr': PIPE

pipe = Popen(['sox','-t','mp3','-', 'test.mp3','trim','0','15'], **kwargs)
output, errors = pipe.communicate(input=open('test.mp3','rb').read())
if errors:
    raise RuntimeError(errors)

这会导致大文件出现问题,因为read() 会将完整的文件加载到内存中;这很慢并且可能导致管道的缓冲区溢出。存在一种解决方法:

from subprocess import Popen, PIPE
import tempfile
import uuid
import shutil
import os

kwargs = 'stdin': PIPE, 'stdout': PIPE, 'stderr': PIPE
tmp = os.path.join(tempfile.gettempdir(), uuid.uuid1().hex + '.mp3')

pipe = Popen(['sox','test.mp3', tmp,'trim','0','15'], **kwargs)
output, errors = pipe.communicate()

if errors:
    raise RuntimeError(errors)

shutil.copy2(tmp, 'test.mp3')
os.remove(tmp)

所以问题如下:除了为 Sox C API 编写 Python 扩展之外,还有其他方法可以替代吗?

【问题讨论】:

【参考方案1】:

SoX 的 Python 包装器已经存在:sox。也许最简单的解决方案是切换到使用它,而不是通过 subprocess 调用外部 SoX 命令行实用程序。

以下使用sox 包(请参阅documentation)在您的示例中实现了您想要的,并且应该在上的Linuxma​​cOS上工作Python 2.73.43.5(它可能也适用于 Windows,但我无法测试,因为我无法访问 Windows框):

>>> import sox
>>> transformer = sox.Transformer()  # create transformer 
>>> transformer.trim(0, 15)  # trim the audio between 0 and 15 seconds 
>>> transformer.build('test.mp3', 'out.mp3')  # create the output file 

注意:这个答案曾经提到不再维护的 pysox 包。感谢@erik 的提示。

【讨论】:

奇怪的是有2011年的pysox Version 0.3.6和2016年的sox 1.2.0, a Python wrapper around SoX。最后一个的github页面命名为pysox!但最后一个不适用于 Python 3。:-( 维护的 python wrapper sox 现在似乎可以与 python 3 一起使用了!并且有 1.3.2 版本。

以上是关于在 Python 中管道 SoX - 子流程替代方案?的主要内容,如果未能解决你的问题,请参考以下文章

将 ffmpeg 流通过管道传输到 sox rec

数字音频处理的瑞士军刀sox的音效算法以及用法

使用命名管道模拟流程替换

使用子流程模块时获取输出档案

渲染管道像素阶段“子流程”

渲染管道像素阶段“子流程”