ffmpeg 中的多个命名管道

2023-12-03

这个问题是后续这个问题

在我的应用程序中,我想修改各种mp3,然后将它们混合在一起。我知道我可以在 FFmpeg 中使用单个命令行来完成此操作,但它最终可能会非常混乱,因为我需要在每个样本上使用各种过滤器,而我有五个过滤器。我的想法是单独编辑每个样本,将它们保存到管道中,最后混合它们。

import subprocess
import os

def create_pipes():
    os.mkfifo("pipe1")
    os.mkfifo("pipe2")

    
def create_samp():   
    sample= subprocess.run(["ffmpeg", "-i", "https://freesound.org/data/previews/186/186942_2594536-hq.mp3", \
                            "-af", "adelay=15000|15000", "-f", "mp3", "pipe:pipe1"], stdout=subprocess.PIPE).stdout
    return(sample)

def create_samp_2():   
    sample= subprocess.run(["ffmpeg", "-i", "https://freesound.org/data/previews/370/370934_6399962-lq.ogg", \
                            "-af", "adelay=1000|1000", "-f", "mp3", "pipe:pipe2"], stdout=subprocess.PIPE).stdout
    return(sample)


def record(samp, samp_2):  
    process = subprocess.Popen(["ffmpeg", "-y", '-f', 'mp3', \
                                "-i", "https://cdns-preview-b.dzcdn.net/stream/c-b0b684fe962f93dc43f1f7ea493683a1-3.mp3", \
                                "-i", "pipe1", \
                                "-i", "pipe2", \
                                "-filter_complex", "amix=inputs=3:duration=longest", "output.mp3"], stdin=subprocess.PIPE)

    process.stdin.write(samp)  
    process.stdin.write(samp_2)
    process.stdin.close()  
    process.wait()

create_pipes()
samp = create_samp()
samp_2 = create_samp_2()
record(samp, samp_2)

当我运行脚本时,create_samp() and create_samp2()运行良好。但我跑record(),程序卡住了,没有错误消息,所以我无法弄清楚问题是什么。


使用命名管道(仅限 Linux):

当有两个或更多输入流(需要从内存缓冲区通过管道传输)时,需要命名管道。
使用命名管道一点也不简单......

从 FFmpeg 的角度来看,命名管道就像(不可查找的)输入文件。

在 Python 中使用命名管道(在 Linux 中):
Assume pipe1是“命名管道”的名称(例如pipe1 = "audio_pipe1").

  1. 创建一个“命名管道”:

    os.mkfifo(pipe1)
    
  2. 将管道打开为“只写”文件:

    fd_pipe = os.open(pipe_name, os.O_WRONLY)  # fd_pipe1 is a file descriptor (an integer).
    
  3. 将数据分成小块写入管道。
    根据thispost,大多数Linux系统中管道的默认缓冲区大小是64KBytes。
    由于数据大于65536字节,我们需要将数据分小块写入管道。
    我决定使用 1024 字节的任意块大小。
    管道写操作是一个“阻塞”操作。
    我通过使用“作家”解决了这个问题thread:

    def writer(data, pipe_name, chunk_size):
        # Open the pipes as opening "low level IO" files (open for "open for writing only").
        fd_pipe = os.open(pipe_name, os.O_WRONLY)  # fd_pipe1 is a file descriptor (an integer)
    
        for i in range(0, len(data), chunk_size):
            # Write to named pipe as writing to a "low level IO" file (but write the data in small chunks).
            os.write(fd_pipe, data[i:chunk_size+i])  # Write 1024 bytes of data to fd_pipe
    
  4. 关闭管道:

    os.close(fd_pipe)
    
  5. 删除(取消链接)命名管道:

    os.unlink(pipe1)
    

这是来自上一篇文章,使用两个命名管道:

import subprocess
import os
from threading import Thread


def create_samp():
    # Read audio stream from https://freesound.org/data/previews/186/186942_2594536-hq.mp3
    # Apply adelay audio filter.
    # Encode the audio in mp3 format.
    # FFmpeg output is passed to stdout pipe, and stored in sample bytes array.
    sample1 = subprocess.run(["ffmpeg", "-i", "https://freesound.org/data/previews/186/186942_2594536-hq.mp3",
                              "-af", "adelay=15000|15000", "-f", "mp3", "pipe:"], stdout=subprocess.PIPE).stdout

    # Read second audio sample from https://cdns-preview-b.dzcdn.net/stream/c-b0b684fe962f93dc43f1f7ea493683a1-3.mp3
    sample2 = subprocess.run(["ffmpeg", "-i", "https://cdns-preview-b.dzcdn.net/stream/c-b0b684fe962f93dc43f1f7ea493683a1-3.mp3",
                              "-f", "mp3", "pipe:"], stdout=subprocess.PIPE).stdout

    return sample1, sample2


def writer(data, pipe_name, chunk_size):
    # Open the pipes as opening files (open for "open for writing only").
    fd_pipe = os.open(pipe_name, os.O_WRONLY)  # fd_pipe1 is a file descriptor (an integer)

    for i in range(0, len(data), chunk_size):
        # Write to named pipe as writing to a file (but write the data in small chunks).
        os.write(fd_pipe, data[i:chunk_size+i])  # Write 1024 bytes of data to fd_pipe

    # Closing the pipes as closing files.
    os.close(fd_pipe)


def record(samp1, samp2):
    # Names of the "Named pipes"
    pipe1 = "audio_pipe1"
    pipe2 = "audio_pipe2"

    # Create "named pipes".
    os.mkfifo(pipe1)
    os.mkfifo(pipe2)

    # Open FFmpeg as sub-process
    # Use two audio input streams:
    # 1. Named pipe: "audio_pipe1"
    # 2. Named pipe: "audio_pipe2"
    # Merge the two audio streams using amix audio filter.
    # Store the result to output file: output.mp3
    process = subprocess.Popen(["ffmpeg", "-y", '-f', 'mp3',
                                "-i", pipe1,
                                "-i", pipe2,
                                "-filter_complex", "amix=inputs=2:duration=longest", "output.mp3"],
                                stdin=subprocess.PIPE)

    # Initialize two "writer" threads (each writer writes data to named pipe in chunks of 1024 bytes).
    thread1 = Thread(target=writer, args=(samp1, pipe1, 1024))  # thread1 writes samp1 to pipe1
    thread2 = Thread(target=writer, args=(samp2, pipe2, 1024))  # thread2 writes samp2 to pipe2

    # Start the two threads
    thread1.start()
    thread2.start()

    # Wait for the two writer threads to finish
    thread1.join()
    thread2.join()

    process.wait()  # Wait for FFmpeg sub-process to finish

    # Remove the "named pipes".
    os.unlink(pipe1)
    os.unlink(pipe2)


sampl1, sampl2 = create_samp()
record(sampl1, sampl2)

Update:

使用类的相同解决方案:
使用类(“NamedPipeWriter"class) 更优雅一点。
该类继承Thread类,并重写run method.

您可以创建多个对象的列表,并在循环中迭代它们(而不是为每个新输入流重复代码)。

这是使用类的相同解决方案:

import subprocess
import os
import stat
from threading import Thread


def create_samp():
    # Read audio stream from https://freesound.org/data/previews/186/186942_2594536-hq.mp3
    # Apply adelay audio filter.
    # Encode the audio in mp3 format.
    # FFmpeg output is passed to stdout pipe, and stored in sample bytes array.
    sample1 = subprocess.run(["ffmpeg", "-i", "https://freesound.org/data/previews/186/186942_2594536-hq.mp3",
                              "-af", "adelay=15000|15000", "-f", "mp3", "pipe:"], stdout=subprocess.PIPE).stdout

    # Read second audio sample from https://cdns-preview-b.dzcdn.net/stream/c-b0b684fe962f93dc43f1f7ea493683a1-3.mp3
    sample2 = subprocess.run(["ffmpeg", "-i", "https://cdns-preview-b.dzcdn.net/stream/c-b0b684fe962f93dc43f1f7ea493683a1-3.mp3",
                              "-f", "mp3", "pipe:"], stdout=subprocess.PIPE).stdout

    return sample1, sample2


class NamedPipeWriter(Thread):
    """ Write data (in small chunks) to a named pipe using a thread """

    def __init__(self, pipe_name, data):
        """ Initialization - get pipe name and data to be written """
        super().__init__()
        self._pipe_name = pipe_name
        self._chunk_size = 1024
        self._data = data
        

    def run(self):
        """ Open the pipe, write data in small chunks and close the pipe """
        chunk_size = self._chunk_size
        data = self._data

        # Open the pipes as opening files (open for "open for writing only").
        fd_pipe = os.open(self._pipe_name, os.O_WRONLY)  # fd_pipe1 is a file descriptor (an integer)

        for i in range(0, len(data), chunk_size):
            # Write to named pipe as writing to a file (but write the data in small chunks).
            os.write(fd_pipe, data[i:chunk_size+i])  # Write 1024 bytes of data to fd_pipe

        # Closing the pipes as closing files.
        os.close(fd_pipe)


    

def record(samp1, samp2):
    # Names of the "Named pipes"
    pipe1 = "audio_pipe1"
    pipe2 = "audio_pipe2"

    # Create "named pipes".
    if not stat.S_ISFIFO(os.stat(pipe1).st_mode):
        os.mkfifo(pipe1)  # Create the pipe only if not exist.

    if not stat.S_ISFIFO(os.stat(pipe2).st_mode):
        os.mkfifo(pipe2)

    # Open FFmpeg as sub-process
    # Use two audio input streams:
    # 1. Named pipe: "audio_pipe1"
    # 2. Named pipe: "audio_pipe2"
    # Merge the two audio streams using amix audio filter.
    # Store the result to output file: output.mp3
    process = subprocess.Popen(["ffmpeg", "-y", '-f', 'mp3',
                                "-i", pipe1,
                                "-i", pipe2,
                                "-filter_complex", "amix=inputs=2:duration=longest", "output.mp3"],
                                stdin=subprocess.PIPE)

    # Initialize two "writer" threads (each writer writes data to named pipe in chunks of 1024 bytes).
    named_pipe_writer1 = NamedPipeWriter(pipe1, samp1)
    named_pipe_writer2 = NamedPipeWriter(pipe2, samp2)

    # Start the two threads
    named_pipe_writer1.start()
    named_pipe_writer2.start()

    # Wait for the two writer threads to finish
    named_pipe_writer1.join()
    named_pipe_writer1.join()

    process.wait()  # Wait for FFmpeg sub-process to finish

    # Remove the "named pipes".
    os.unlink(pipe1)
    os.unlink(pipe2)


sampl1, sampl2 = create_samp()
record(sampl1, sampl2)

Notes:

  • 该代码在 Ubuntu 18.04(虚拟机)中进行了测试。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ffmpeg 中的多个命名管道 的相关文章

  • ResultSet 对象没有属性“find_all”

    当我抓取一个网页时 我总是遇到一个问题 AttributeError ResultSet 对象没有属性 find 您可能将项目列表视为单个项目 当您打算调用 find 时 您是否调用了 find all 谁能告诉我如何解决这个问题 我的代码
  • Django 自引用关系?

    我正在尝试创建模型页面 页面也应该能够有 子页面 我的模型代码如下使Python崩溃 http pastie org private butthk1aaeb3pmh7mmag1g在我的Mac python 2 6 1 和Ubuntu 10
  • Ubuntu 上的 Chromedriver:selenium.common.exceptions.SessionNotCreatedException:消息:会话未创建

    我在 AWS EC2 实例 的 Ubuntu 环境中使用 Selenium Chromedriver 时遇到问题 我正在使用 Chromedriver Linux64 版本 wnload chromedriver for Linux wge
  • 使用 JSON 将数据从 Python 导出到 Tableau?

    如何以表格形式从 Python 获取 400 万行和 28 列 我假设 基于搜索 我应该使用 JSON 格式 这种格式可以处理大量数据并且足够快 我制作了 12 行数据的子集并尝试使其正常工作 好消息是 它正在发挥作用 坏消息 不是我想要的
  • Python XLWT调整列宽

    XLWT 的易用性给我留下了深刻的印象 但有一件事我还没有弄清楚该怎么做 我正在尝试将某些行调整为显示所有字符所需的最小宽度 换句话说 如果双击单元格之间的分隔线 excel 会做什么 我知道如何将列宽调整为预定量 但我不确定如何确定显示所
  • Python + Selenium:驱动程序路径

    是否有可能在不输入路径的情况下运行 Python Selenium 脚本exePython 行中每个脚本中的文件 driver webdriver Chrome 同样的问题也适用于 IE 驱动程序 Edge 驱动程序 和 Gecko 驱动程
  • AMLS 实验运行停留在“正在运行”状态

    我运行了 Azure 机器学习服务实验 并使用 Jupyter Notebook 记录了神经网络损失 日志记录工作正常 神经网络训练也按预期完成 但实验一直停留在运行状态 关闭计算资源不会关闭实验运行 我无法从实验面板取消它 此外 运行没有
  • 如何有效地找到两个轮廓集之间的所有交点

    我想知道找到两组轮廓线之间所有交点 舍入误差 的最佳方法 哪种方法最好 这是示例 import matplotlib pyplot as plt import numpy as np x np linspace 1 1 500 X Y np
  • OSMNX - 边缘的哪个“部分”被认为是最近的

    我正在使用 OSMNX 中的 returned edges 函数 我不清楚在进行此计算时使用边缘的哪个 部分 它是边缘的任何部分吗 是中间点吗 对于网络中的长边来说 这会产生很大的差异 这取决于您如何参数化该函数 来自nearest edg
  • tkinter - 在askopenfile期间检索文件名

    我有一个用 Python 和 tkinter 制作的文本编辑器 这是我的 打开文件 方法 def onOpen self file askopenfile filetypes Text files txt txt file read sel
  • Pygame - 两个圆圈的碰撞检测

    我正在制作一个碰撞检测程序 其中我的光标是一个半径为 20 的圆 当它碰到另一个圆时应该将值更改为 TRUE 出于测试目的 我在屏幕中心有一个半径为 50 的固定圆 我可以测试光标圆是否击中固定圆 但它不能正常工作 因为它实际上是在测试它是
  • 重置Keras模型的所有权重

    我希望能够重置整个 Keras 模型的权重 这样我就不必再次编译它 编译模型目前是我的代码的主要瓶颈 这是我的意思的一个例子 import tensorflow as tf model tf keras Sequential tf kera
  • 由 asyncio.new_event_loop 创建的事件循环挂起

    以下代码只是挂起而不打印任何内容 import asyncio async def foo loop print foo loop stop loop asyncio new event loop asyncio ensure future
  • 如何向 Iron Python 添加模块?

    我一直在尝试使用 C Visual Studio 执行以下 Python 代码 graphcreater py 我通过 NuGet 包管理器添加了 IronPyton 2 7 7 和 IronPython StdLib 2 7 7 一旦我运
  • 相比之下,超出了最大递归深度

    我写了这段代码来计算组合的数量 def fact n return 1 if n 1 else n fact n 1 def combinations n k return fact n fact n k fact k while True
  • Django 和 REST API 服务基于计算的请求

    我在 Django 中编写了一个机器学习应用程序 以便用户可以在表单中指定一些参数并训练模型 模型训练完成后 我想满足以下请求 curl http localhost 8000 model input XYZ 我希望 Django 返回给定
  • pandas 数据帧和聚合中的行明智排序

    我在 pandas dataframe df 中有一个表 col1 col2 count 12 15 3 13 17 5 1 36 4 15 12 7 36 1 4 等等 我想要的是将 12 和 15 和 15 和 12 等计算值视为相同
  • 在 AWS ec2 实例上使用“sudo pip”时出现错误

    我正在尝试在 aws ec2 实例上运行一个小型 python 代码 需要 pytz 和其他一些包 当我尝试安装 pytz 时 出现一些错误 ec2 user ip 172 31 28 178 pip install pytz Collec
  • 如何在(最好是纯)Python 中解码 QR 码图像?

    TL DR 我需要一种使用 最好是纯 Python 从图像文件中解码 QR 码的方法 我有一个带有 QR 码的 jpg 文件 我想使用 Python 对其进行解码 我发现有几个库声称可以做到这一点 PyQRCode 网站在这里 http p
  • 命名空间与常规包

    命名空间 Python 包之间有什么区别 没有 init py 和一个常规的Python包 有一个 init py 特别是当 init py普通包裹是空的吗 我很好奇 因为最近我忘记了 init py在我制作的包中 我从未注意到任何问题 事

随机推荐

  • Html Agility Pack - <选项> 内部文本

    我对这个 html 有问题
  • Windows 7 - 无法更新 C:\Program Files 中的程序文​​件

    我有一个与 MS Word 2007 版 一起使用的插件程序 它位于 C Program Files 位置 我安装了 Windows 7 然后对这个位置的文件进行了例行更改 但它只会显示一个只读文件 我怎样才能授予自己写入我自己的程序的权限
  • 如何从 Wappalyzer 中隐藏 Yii Web 框架名称?

    我试图从 Chrome Firefox 的 Wappalyzer 插件中隐藏框架名称 Yii 我需要隐藏框架名称作为安全审核的一部分 我已经在 Apache 配置中关闭了服务器签名 但框架名称 Yii 仍然显示 您可以了解 Wappalyz
  • Rails 4:在哪里放置 JavaScript/CSS 插件

    我有 Rails 4rc1 应用程序 我需要将一些 JavaScript CSS 插件 第三方库 集成到我的应用程序中 我知道 Rails 4 中不推荐使用供应商 插件目录 那么我可以在哪里放置 JavaScript CSS 插件呢 听起来
  • 如何解释此错误“UnicodeDecodeError:‘ascii’编解码器无法解码位置 164 中的字节 0xe2:序号不在范围(128)内”

    我正在尝试在 python 3 中运行以下代码 def func file for file in os listdir cwd if file endswith html f open file r text re sub r cat f
  • Firefox 的错误 - 刷新时输入的禁用属性未重置

    我发现了一个我认为是 Firefox 的错误 我想知道这是否真的是一个错误 以及解决这个问题的方法 如果您使用以下源创建一个基本网页 div div
  • 在 Ado.net C# 中动态构建Where子句

    我将在给定时间接收大约 1000 条记录 并且必须确定它们是现有记录还是新记录 如果它们存在 我必须更新记录 如果是新的 则只需插入它们 我不知道它们是否会存在 或者是否全部存在 我认为最好对数据库进行一次查询 并尝试查找数据库中是否存在其
  • IIS 7 URL 重写匹配 URL

    我正在尝试使用 URL 重写模块在 IIS 7 中设置规范的默认 URL 我认为我误解了 匹配 URL 字段的使用方式 以下似乎没有做任何事情
  • 使用事件调度程序自动备份

    我正在尝试使用 MySQL 中的事件调度程序创建自动备份 这是我的脚本 CREATE DEFINER root localhost EVENT Backup ON SCHEDULE EVERY 1 WEEK STARTS 2013 06 1
  • 事件触发之前的对象处置和垃圾收集

    与我交谈的某人提出了一段代码 private void DownloadInformation string id using WebClient wc new WebClient wc DownloadStringCompleted ne
  • 在java中实现抽象方法/类

    我可以在java中的抽象基类A中实现抽象方法吗 如果答案是肯定的 并且基类 A 中有一个已实现的抽象方法 并且有一个来自 A 的派生类 B B 不是抽象的 B 还必须实现那个基本抽象方法吗 如果我正确理解你的问题 是的 public abs
  • 在两个未在 twilio 中注册的号码之间拨打电话

    有什么方法可以在我的两个用户之间拨打电话吗 我的意思是 我有一个带有注册号码的 twilio 帐户 我必须给我的客户 Bill 打电话 所以当他接听电话时 电话应该重定向到 Bill 选择的另一个客户 让我们说 Joe 因此 比尔点击了一个
  • 使用静态函数实现特征对特征

    trait Trait
  • 如何在c#中从RGB555转换为RGB888?

    我需要将 16 位 XRGB1555 转换为 24 位 RGB888 我的函数如下 但它并不完美 即值 0b11111 将给出 248 作为像素值 而不是 255 该函数适用于小端 但可以轻松修改为大端 public static Colo
  • 工头没有反映变化

    我用这篇文章搭建了facebook app开发的开发环境 https devcenter heroku com articles facebook create an app除了 FOREMAN 之外 一切都很好 问题是 每次我在脚本中进行
  • 如何在matlab中绘制非线性微分方程

    Dx y Dy k y x 3 9 8 cos t inits x 0 0 y 0 0 这些是我想要绘制的微分方程 首先 我尝试求解微分方程 然后绘制图形 Dsolve Dx y Dy k y x 3 9 8 cos t inits 然而
  • android openFileOutput 有什么问题?

    我正在尝试使用 openFileOutput 函数 但它无法编译并且无法识别该函数 我使用的是android sdk 1 6 这是sdk的问题吗 这是参数问题吗 import java io FileOutputStream public
  • 约束最小二乘法

    我正在 R 中对人均天然气使用量进行简单回归 回归公式如下 gas b lt lm log gasq pop log gasp log pcincome log pn log pd log ps log years data gas sum
  • 带有图像和 2 TextView 的 TableRow

    我在做这样的事情时遇到问题 http imageshack us photo my images 824 examplehm png 我的 xml 代码在行中显示 3 列 但我想要 2 列 并且第二列必须分为两个水平部分 My xml
  • ffmpeg 中的多个命名管道

    这个问题是后续这个问题 在我的应用程序中 我想修改各种mp3 然后将它们混合在一起 我知道我可以在 FFmpeg 中使用单个命令行来完成此操作 但它最终可能会非常混乱 因为我需要在每个样本上使用各种过滤器 而我有五个过滤器 我的想法是单独编