簡體   English   中英

python-subprocess.Popen無法正確傳遞urllib3響應

[英]python - subprocess.Popen fails to correctly pipe urllib3 Response

我想通過網絡打開文件,然后使用subprocess.Popen將其直接傳輸到ffmpeg。 目標是將音頻文件數據直接流式傳輸到ffmpeg。 這是代碼:

# test.py
import subprocess, sys, urllib3, time

http = urllib3.PoolManager()
r = http.urlopen('GET', sys.argv[1], preload_content=False)

args = 'ffmpeg -i - -y audio.mp3'.split(' ')
subprocess.Popen(args, stdin=r)

r.close()

如果我運行本地HTTP服務器並為程序提供url,則它可以成功運行,並且ffmpeg對其進行處理。

$ python3 test.py http://192.168.1.200/original.webm

但是,如果我嘗試從遠程服務器(如下面的服務器)中檢索,則ffmpeg失敗。

$ python3 test.py https://cdn.discordapp.com/attachments/304959901376053248/412003156638040084/original.webm

具有以下輸出

pipe:: Invalid data found when processing input

我希望這段代碼產生與運行此終端命令相同的結果。 對於不一致的CDN URL和本地HTTP服務器URL,此命令均成功。

$ curl [file url] | ffmpeg -i - -y audio.mp3

我在Linux和ffmpeg 3.4.1上使用python 3.5。

編輯1

我現在傾向於認為這不是ffmpeg的錯,更多地是關於Popen如何讀取/編寫對進程stdin的urllib響應的。 通過運行本地netcat服務器並將輸出發送到文件( $ nc -l 1234 > nc_output.webm )並按以下方式調整腳本:

import subprocess, sys, urllib3, time

http = urllib3.PoolManager()
r = http.urlopen('GET', sys.argv[1], preload_content=False)

args = 'nc 192.168.1.200 1234'.split(' ')
subprocess.run(args, stdin=r)

r.close()

然后以$ python3 test.py https://cdn.discordapp.com/attachments/304959901376053248/412003156638040084/original.webm運行

通過將nc_output.webm與原始.webm文件進行比較,我可以立即看到nc_output.webm稍大一些(4017585字節,而4008589字節)。 嘗試播放nc_output.webm(mpv,vlc,ffprobe)也失敗,這說明了ffmpeg抱怨的原因。 Popen對流的字節所做的任何事情都足以使輸出文件無用。

但是,如果URL指向本地HTTP服務器,例如從python -m SimpleHTTPServer運行的URL,該問題仍然不會繼續發生,這使我認為這與與從遠程源讀取有關的延遲有關。

urllib3實現使用Python代碼從打開的連接中獲取內容。 這在Python客戶端上很棒,但是無法跨子進程邊界工作。

您正在使用subprocess.Popen() ,它實際上使您可以相對輕松地解決此問題。 您正在子ffmpeg中啟動ffmpeg ,但是控制返回到您的Python代碼,而子進程仍在后台,等待您將其輸入標准輸入數據。

r = http.urlopen('GET', sys.argv[1], preload_content=False)

# Manually split the command, just for aesthetics
s = subprocess.Popen(['ffmpeg', '-i', '-', '-y', 'audio.mp3'], stdin=subprocess.PIPE)
while True:
    b = r.read(8192)
    if b == '':
        break
    s.communicate(b)
r.close()
s.close()

暫無
暫無

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

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