簡體   English   中英

FFmpeg save.mp3 output 成變量

[英]FFmpeg save .mp3 output into a variable

在我的應用程序中,我想修改各種 mp3,然后將它們混合在一起。 我知道我可以使用 FFmpeg 中的單個命令行來完成它,但它最終可能會非常混亂,因為我需要在每個樣本上使用各種過濾器並且我有五個。 我的想法是單獨編輯每個樣本,將它們保存到變量中,最后混合它們。 這是我的代碼:

import subprocess    

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

def record(samp):
    subprocess.run(["ffmpeg", "-y", "-i", "https://cdns-preview-b.dzcdn.net/stream/c-b0b684fe962f93dc43f1f7ea493683a1-3.mp3", \
                    "-i", samp.stdout, "-f", "-mp3", "copy", "output.mp3"])

samp = create_samp()
record(samp)

我的問題是我必須對stdout進行編碼。 我試過'utf-8'但得到這個錯誤:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 45: invalid start byte

使用“utf-16”:

UnicodeDecodeError: 'utf-16-le' codec can't decode bytes in position 239454-239455: illegal encoding

為什么要解決這個問題? 我的方法是正確的嗎?

感謝@Rotem,我成功地做了我想做的事。 但現在我面臨另一個問題,因為我想混合多達 5 種聲音,所以我嘗試以懶惰/簡單的方式實現它:

import subprocess

def create_samp_2():
    sample= 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
    return(sample)

def create_samp():

    sample= subprocess.run(["ffmpeg", "-i", "https://freesound.org/data/previews/370/370934_6399962-lq.ogg", \
                            "-af", "adelay=1000|1000", "-f", "mp3", "pipe:"], 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", "pipe:", \
                                "-i", "pipe:", \
                                "-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()

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

令人驚訝的是它有效,我的兩個聲音在正確的時間開始,但第二個聲音搞砸了。 所以這不是正確的方法。

然后我按照這種方式嘗試了命名管道:

"pipe1:"

但我得到這個錯誤:

pipe1:: Protocol not found
Did you mean file:pipe1:?

閱讀名為 pipe wiki 的內容,據說我必須使用mkfifo()創建它們。

所以我嘗試了:

import os
pipe1 = "pipe1"

def create_pipe1():
    os.mkfifo(pipe1)

But now I have this error: pipe1:: Protocol not found
Did you mean file:pipe1:?

您的方法是正確的,但需要修復。

修復create_samp()

  • 您不需要"-codec:v", "copy" arguments,因為沒有視頻 stream。

修復record(samp)

  • 您不能使用"-i" "samp.stdout" ,因為samp.stdout是一個字節數組(Python 子進程模塊將其用作字符串)。
  • 使用"-i", "pipe:"從標准輸入 pipe 接收第二個音頻。
  • 由於您想混合兩個音頻流,因此您必須使用"-filter_complex"參數,以及amix音頻過濾器或amerge音頻過濾器,如此所述。
  • samp寫入 stdin pipe,並關閉 stdin pipe。

這是代碼:

import subprocess

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.
    sample= 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
    return(sample)


def record(samp):
    # Open FFmpeg as sub-process
    # Use two audio input streams:
    # 1. WEB address
    # 2. PIPE (the input is going to be written stdin pipe).
    # 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", "https://cdns-preview-b.dzcdn.net/stream/c-b0b684fe962f93dc43f1f7ea493683a1-3.mp3", \
                                "-i", "pipe:", \
                                "-filter_complex", "amix=inputs=2:duration=longest", "output.mp3"], stdin=subprocess.PIPE)

    process.stdin.write(samp)  # Write samp (bytes array containing mp3 data).
    process.stdin.close()  # Close stdin pipe.
    process.wait()  # Wait for FFmpeg sub-process to finish

samp = create_samp()
record(samp)

聽起來很棒...


更新:

命名管道實現移至以下帖子。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM