通过omxplayer从Python进程的内存中播放MP3,而无需写入磁盘 读者背景方法1:使用Shell进行文件描述符处理方法2:使用命名管道方法3:在Python中使用omxplayer

问题描述

以下代码接收MP3,将其写入磁盘并使用OMXPlayer播放。我想避免在播放MP3之前将其写入磁盘。

song = response.content
file = open("temp.mp3","wb")
file.write(song)
file.close()
response.close()
play_song_subprocess = subprocess.call(['omxplayer','-o','local','--vol','-500','temp.mp3'])

如何消除file.write()? 我正在寻找做这样的事情:

song = response.content
play_song_subprocess = subprocess.call(['omxplayer',song])

但这会导致以下错误: 嵌入的空字节

解决方法

读者背景

建立在聊天和评论中:

  • tiff("test.tiff",units="in",width=5,height=5,res=300) # insert ggplot code dev.off() 导致段错误。
  • cat temp.mp3 | omxplayer -o local --vol -500 /dev/stdin正常工作。

因此,我们可以在...上传递MP3的数据,但不能在stdin上传递(omxplayer -o local --vol -500 /dev/fd/3 3< <(cat temp.mp3)用于控制:暂停,提早退出等)。


方法1:使用Shell进行文件描述符处理

这等效于“方法3”,但是它没有使用非常新的和现代的Python功能来进行FD处理过程,而是启动了omxplayer的副本来完成工作(因此将工作以及更老的Python版本)。

/bin/sh

由于play_from_stdin_sh = ''' exec 3<&0 # copy stdin to FD 3 exec </dev/tty || exec </dev/null # make stdin now be /dev/tty or /dev/null exec omxplayer -o local --vol -500 /dev/fd/3 # play data from FD 3 ''' p = subprocess.Popen(['sh','-c',play_from_stdin_sh],stdin=subprocess.POPEN) p.communicate(song) # passes data in "song" as stdin to the copy of sh 希望使用stdin从其用户那里获取指令,因此我们需要使用其他文件描述符来传递其内容。因此,尽管我们让Python解释器在stdin上传递内容,然后我们将shell复制stdin到FD 3,并在调用{{1}之前用句柄或omxplayer/dev/tty替换了原始stdin }。


方法2:使用命名管道

关于这是否欺骗了“不写磁盘”约束,还有一个问题。它不会将任何MP3数据写入磁盘,但是会创建创建一个文件系统对象,即使写入该对象的数据流了,这两个进程也可以打开该文件系统对象作为彼此连接的方式直接在进程之间进行,而无需写入磁盘。

/dev/null

方法3:在Python中使用omxplayer

我们可以实现文件描述符,方法1使用import tempfile,os,os.path,shutil,subprocess fifo_dir = None try: fifo_dir = tempfile.mkdtemp('mp3-fifodir') fifo_name = os.path.join(fifo_dir,'fifo.mp3') os.mkfifo(fifo_name) # now,we start omxplayer,and tell it to read from the FIFO # as long as it opens it in read mode,it should just hang until something opens # ...the write side of the FIFO,writes content to it,and then closes it. p = subprocess.Popen(['omxplayer','-o','local','--vol','-500',fifo_name]) # this doesn't actually write content to a file on disk! instead,it's written directly # ...to the omxplayer process's handle on the other side of the FIFO. fifo_fd = open(fifo_name,'w') fifo_fd.write(song) fifo_fd.close() p.wait() finally: shutil.rmtree(fifo_dir) 对象的preexec_fn参数在本机Python中使用了shell。考虑:

Popen