- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个程序使用类似于以下内容的方式将帧作为字符串发送到 FFMPEG:
#!/usr/bin/python
import sys, os
import subprocess as sp
import pygame
from pygame.locals import QUIT, KEYUP, K_ESCAPE
import pygame.display
pygame.init()
os.environ['SDL_VIDEODRIVER'] = 'dummy'
pygame.display.init()
Display_Surface = pygame.display.set_mode([1280,720], 0, 32)
# FFMPEG command and settings
command = ['ffmpeg', '-framerate', '25', '-s', '1280x720', '-pix_fmt', 'rgba', '-f', 'rawvideo', '-i', '-',
'-f', 'lavfi', '-i', 'anullsrc=cl=mono',
'-pix_fmt', 'yuv420p','-s', 'hd720', '-r', '25', '-g', '50',
'-f', 'flv', 'rtmp://a.rtmp.youtube.com/live2/xxxx-xxxx-xxxx-xxxx']
pipe = sp.Popen(command, bufsize=0, stdin=sp.PIPE)
while True:
# Quit event handling
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
pipe.stdin.write(pygame.image.tostring(Display_Surface, "RGBA"))
pipe.stdin.close()
pygame.display.quit()
os._exit()
这工作正常,除了它会占用我的 CPU,这反过来会导致我的实时流经常卡住。愚蠢的 GIL 不会让 FFMPEG 在另一个 CPU/核心上运行,而我有 3 个非常好的核心什么都不做。
我刚刚编写了一些代码以在另一个进程中打开 FFMPEG。 (顺便说一句,我熟悉 threading.Thread,但不熟悉 Multiprocessing)。
import os
import subprocess as sp
import multiprocessing
class FFMPEG_Consumer():
def __init__(self):
proc = multiprocessing.Process(target=self.start_ffmpeg)
proc.start()
def start_ffmpeg(self):
command = ['ffmpeg','-pix_fmt', 'rgba', '-f', 'rawvideo', '-i', '-',
'-f, 'lavfi', '-i', 'anullsrc=channel_layout=stereo:sample_rate=44100',
'-pix_fmt', 'yuv420p','-s', 'hd720', '-f', 'flv', 'rtmp://example.com']
pipe = sp.Popen(command, bufsize=-1, stdin=sp.PIPE)
def send_down_the_pipe(self, frame):
pipe.stdin.write(frame)
ffmpeg = FFMPEG_Consumer()
对于任何知道如何使用多处理的人,我相信您会立即发现这是行不通的,因为我不能以这种方式跨进程共享变量。但是,它确实在另一个核心上打开了 FFMPEG。
大多数在线教程和资源都侧重于创建工作人员池和队列,以向这些工作人员发送需要处理的内容,直到作业完成。然而,我试图通过每次迭代向 FFMPEG 重复发送一个新字符串。
如何将我的字符串通过管道传输到 FFMPEG 的进程/实例?
或者我想做的是不可能的?
#!/usr/bin/python
import sys, os, multiprocessing
import subprocess as sp
import pygame
from pygame.locals import QUIT, KEYUP, K_ESCAPE
import pygame.display
pygame.init()
os.environ['SDL_VIDEODRIVER'] = 'dummy'
pygame.display.init()
Display_Surface = pygame.display.set_mode([1280,720], 0, 32)
class FFMPEGConsumer(object):
def __init__(self):
self._r, self._w = multiprocessing.Pipe()
self.reader = os.fdopen(self._r.fileno(), 'r')
self.writer = os.fdopen(self._w.fileno(), 'w', 0)
self.proc = None
def start_ffmpeg(self):
command = ['ffmpeg', '-framerate', '25', '-s', '1280x720', '-pix_fmt', 'rgba', '-f', 'rawvideo', '-i', '-',
'-f', 'lavfi', '-i', 'anullsrc=cl=mono',
'-pix_fmt', 'yuv420p','-s', 'hd720', '-r', '25', '-g', '50',
'-f', 'flv', 'rtmp://a.rtmp.youtube.com/live2/xxxx-xxxx-xxxx-xxxx']
self.proc = sp.Popen(command, bufsize=-1, stdin=self.reader)
def send_down_the_pipe(self, frame):
self.writer.write(frame)
#print self._stdin.read()
def __del__(self):
self.reader.close()
self.writer.close()
ffmpeg = FFMPEGConsumer()
while True:
# Quit event handling
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
ffmpeg.send_down_the_pipe(pygame.image.tostring(Display_Surface, "RGBA"))
proc.join()
pipe.stdin.close()
pygame.display.quit()
os._exit()
所有核心都在发射,到目前为止没有滞后!!!
最佳答案
您可以使用 multiprocessing.Pipe
与子进程通信。
multiprocess.Pipe
为您提供管道的两端,其中一端可用于写入,另一端用于读取,反之亦然(如果双工标志设置为 True)。这两端的事情是那些只是文件描述符。这就是为什么你需要打开它们,就像文件一样,然后读/写。要打开它们,您必须使用 os.fdopen
。从此就像读/写文件一样。
像这样的东西应该有帮助:
import os
import subprocess as sp
import multiprocessing
class FFMPEG_Consumer():
def __init__(self):
r, w = multiprocessing.Pipe()
self._stdin = os.fdopen(r.fileno(), 'r')
self._stdout = os.fdopen(w.fileno(), 'w')
proc = multiprocessing.Process(target=self.start_ffmpeg)
proc.start()
def start_ffmpeg(self):
command = ['ffmpeg', '-pix_fmt', 'rgba', '-f', 'rawvideo', '-i', '-', '-f',
'lavfi', '-i', 'anullsrc=channel_layout=stereo:sample_rate=44100',
'-pix_fmt', 'yuv420p', '-s', 'hd720', '-f', 'flv', 'rtmp://example.com']
sp.Popen(command, bufsize=-1, stdin=self._stdin)
def send_down_the_pipe(self, frame):
self._stdout.write(frame)
ffmpeg = FFMPEG_Consumer()
ffmpeg.send_down_the_pipe(frame)
您可以调整缓冲以更好地满足您的需求。当您使用 os.fdopen
时,第三个参数是缓冲区大小。 0
是完全不缓冲打开
我不想出于教育目的删除旧版本。我之前的脚本有什么问题?
class FFMPEG_Consumer():
def __init__(self):
r, w = multiprocessing.Pipe()
self._stdin = os.fdopen(r.fileno(), 'r')
self._stdout = os.fdopen(w.fileno(), 'w')
...
__init__
方法执行后,r
和w
文件描述符被垃圾回收。现在,您有 self._stdin
和 self._stdout
仍然存在并指向不存在的文件描述符。实例化 FFMPEG_Consumer
后,您会收到以下错误:
close failed in file object destructor:
IOError: [Errno 9] Bad file descriptor
close failed in file object destructor:
IOError: [Errno 9] Bad file descriptor
如何解决?您必须确保在实例化 FFMPEG_Consumer
之后保留文件描述符。
在展示如何解决这个问题的示例脚本之前,让我给你几个建议:
object
的原因。您将在示例脚本中看到它。FFMPEGConsumer
优于 FFMPEG_Consumer
。现在进入工作示例。
这是我使用的两个脚本,可以让任何人在不使用 ffmpeg
的情况下测试它的工作原理。 注意:此为Python2.7版本
脚本 so6_reader.py
需要用户输入:
#!/usr/bin/env python2.7
if __name__ == "__main__":
for i in range(2):
a = raw_input('Enter the string: ')
print 'You entered %s' % a
启动子进程的脚本,该子进程启动 so6_reader.py
并写入其标准输入。
#!/usr/bin/env python2.7
import os
import multiprocessing
import subprocess as sp
class FFMPEGConsumer(object):
def __init__(self):
self._r, self._w = multiprocessing.Pipe()
self.reader = os.fdopen(self._r.fileno(), 'r')
self.writer = os.fdopen(self._w.fileno(), 'w', 0)
self.proc = None
def start_ffmpeg(self):
command = ['python', 'so6_reader.py']
self.proc = sp.Popen(command, bufsize=0, stdin=self.reader)
def send_down_the_pipe(self, frame):
self.writer.write(frame)
def __del__(self):
self.reader.close()
self.writer.close()
ffmpeg = FFMPEGConsumer()
proc = multiprocessing.Process(target=ffmpeg.start_ffmpeg)
proc.start()
ffmpeg.send_down_the_pipe('test 001\n')
ffmpeg.send_down_the_pipe('test 002\n')
proc.join()
关于python - 如何使用带有 Mutliprocessing 的 PYTHON 打开程序,并从主进程向其发送字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48722876/
我想使用 li 和 ul 制作一个多级下拉列表,以便显示我博客中按年和月排序的所有文章。我希望我的下拉菜单看起来像 Google Blogspot 下拉菜单: 这是我的 CSS 和 HTML 代码 u
我在 Win 7 64 机器上将 CodeBlocks 与 gcc 4.7.2 和 gmp 5.0.5 结合使用。开始使用 gmpxx 后,我看到一个奇怪的段错误,它不会出现在 +、- 等运算符中,但
我正在使用 tern 为使用 CodeMirror 运行的窗口提供一些增强的智能感知,它工作正常,但我遇到了一个问题,我想添加一些自定义“types”,可以这么说,这样下拉列表中它们旁边就有图标了。我
我正在尝试让我的 PC 成为 Android 2.3.4 设备的 USB 主机,以便能够在不需要实际“附件”的情况下开发 API。为此,我需要将 PC 设置为 USB 主机和“设备”(在我的例子中是运
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 9
我在设置服务器方面几乎是个新手,但遇到了一个问题。我有一个 Ubuntu 16.04 VPS 并安装了 Apache2 和 Tomcat7。我正在为 SSL 使用 LetsEncrypt 和 Cert
我在一个基于谷歌地图的项目上工作了超过 6 个月。我使用的是 Google Maps API V1 及其开发人员 API key 。当我尝试发布应用程序时,我了解到 Google API V1 已被弃
我是 Python 的新手,所以如果我对一些简单的事情感到困惑,请原谅。 我有一个这样的对象: class myObject(object): def __init__(self):
这个问题已经有答案了: How can I access object properties containing special characters? (2 个回答) 已关闭 9 年前。 我正在尝
我有下面的 CSS。我想要的是一种流体/液体(因为缺乏正确的术语)css。我正在为移动设备开发,当我改变模式时 从纵向 View 到陆地 View ,我希望它流畅。现在的图像 在陆地 View 中效
我正在尝试使用可以接受参数的缓存属性装饰器。 我查看了这个实现:http://www.daniweb.com/software-development/python/code/217241/a-cac
这个问题在这里已经有了答案: Understanding slicing (36 个答案) 关闭 6 年前。 以a = [1,2,3,4,5]为例。根据我的直觉,我认为 a[::-1] 与 a[0:
mysqldump -t -u root -p mytestdb mytable --where=datetime LIKE '2014-09%' 这就是我正在做的事情,它会返回: mysqldum
我正在制作销售税计算器,除了总支付金额部分外,其他一切都正常。在我的程序中,我希望能够输入一个数字并获得该项目的税额我还希望能够获得支付的总金额,包括交易中的税金。到目前为止,我编写的代码完成了所有这
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许在 Stack Overflow 上提出有关通用计算硬件和软件的问题。您可以编辑问题,使其成为
我是否必须进行任何额外的设置才能让 apache-airflow 在任务失败时向我发送电子邮件。我的配置文件中有以下内容(与默认值保持不变): [email] email_backend = airf
这个问题在这里已经有了答案: What does the $ symbol do in VBA? (5 个回答) 3年前关闭。 使用返回字符串(如 Left)的内置函数有什么区别吗?或使用与 $ 相同
我有一个用VB6编写的应用程序,我需要使用一个用.NET编写的库。有什么方法可以在我的应用程序上使用该库吗? 谢谢 最佳答案 这取决于。您可以控制.NET库吗? 如果是这样,则可以修改您的库,以便可以
当我创建一个以 ^ 开头的类方法时,我尝试调用它,它给了我一个错误。 class C { method ^test () { "Hi" } } dd C.new.test; Too m
我已经使用 bower 安装了 angularjs 和 materialjs。 凉亭安装 Angular Material 并将“ngMaterial”注入(inject)我的应用程序,但出现此错误。
我是一名优秀的程序员,十分优秀!