从Python进程播放MP3';通过omxplayer访问内存,无需写入磁盘

从Python进程播放MP3';通过omxplayer访问内存,无需写入磁盘,python,omxplayer,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',

下面的代码接收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'])
如何消除
文件.write()
? 我想做这样的事情:

song = response.content
play_song_subprocess = subprocess.call(['omxplayer', '-o', 'local', '--vol', '-500', song])
但这会导致以下错误: 嵌入式空字节

读者背景故事 在聊天和评论中建立:

  • cat temp.mp3 | omxplayer-o local--vol-500/dev/stdin
    导致SEG故障

  • omxplayer-o local--vol-500/dev/fd/3cat file.mp3 | omxplayer-o local--vol-500/dev/stdin
    ;如果从
    /dev/stdin
    中读取内容有效,那么我们应该能够编写同样有效的Python。(该测试的原因是FIFO是不可查找的:它只能从开始到结束读取一次;不能向前跳、向后退等;并非所有用于操作媒体文件的软件都可以这样操作——有时他们希望能够多次读取内容,或者向前跳到页脚,等等)。(顺便说一句,只是为了解释“嵌入的空字节”错误--命令行由C字符串列表组成。C字符串由它们包含的第一个NUL终止;因此,您不能将包含任何NUL的数据放入命令行参数中。并且无论如何--
    omxplayer
    希望该位置的任何内容都是文件名,而不是要播放的数据;如果它试图打开您的data就好像它是一个文件名一样,您可能会在以后遇到另一个错误。)@CharlesDuffy感谢您的评论,但是subprocess.call()并不总是需要文件系统操作。例如:subprocess.call(['omxplayer','-o','local','--vol','-500',')很好。是的,我知道你的意思。这就是为什么我告诉你用
    /dev/stdin
    运行测试的原因(我正焦急地等待对该测试的回应)。但问题的关键是,最初的问题标题要求的是一些从迂腐的意义上说不可能的东西,因此,更清晰的标题会改善情况。
    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)
    
    import os, subprocess
    
    def move_stdin():
      os.dup2(0, 3)                       # copy our stdin -- FD 0 -- to FD 3
      try:
        newstdin = open('/dev/tty', 'r')  # open /dev/tty...
        os.dup2(newstdin.fileno(), 0)     # ...and attach it to FD 0.
      except IOError:
        newstdin = open('/dev/null', 'r') # Couldn't do that? Open /dev/null...
        os.dup2(newstdin.fileno(), 0)     # ...and attach it to FD 0.
    
    p = subprocess.Popen(['omxplayer', '-o', 'local', '--vol', '-500', '/dev/fd/3'],
                         stdin=subprocess.PIPE, preexec_fn=move_stdin, pass_fds=[0,1,2,3])
    p.communicate(song)