如何在播放视频时打开和关闭 omxplayer (Python/Raspberry Pi)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26389648/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 00:25:57  来源:igfitidea点击:

How to open and close omxplayer (Python/Raspberry Pi) while playing video?

pythonmultithreadingsubprocessraspberry-pigpio

提问by jmcclaire

Using a Raspberry Pi and some push buttons I want to control video playback. When someone presses a button the corresponding video plays. The buttons work great. When you press a button the video plays, but when you press a different button or the same button it opens the video without closing the video that was currently playing. I've been searching a while to fix this. I'm pretty new to Python so please keep it as simple as possible. In the code below I'm trying to accomplish it using multithreading. I wasn't able to close the thread though when another thread starts. I am able to close the video after it plays for 10 seconds, but I can't move the quit command anywhere else to close other videos: playSippycup.stdin.write('q')

使用 Raspberry Pi 和一些按钮,我想控制视频播放。当有人按下按钮时,相应的视频就会播放。按钮很好用。当您按下按钮时,视频会播放,但是当您按下不同的按钮或相同的按钮时,它会打开视频而不关闭当前正在播放的视频。我一直在寻找一段时间来解决这个问题。我对 Python 很陌生,所以请尽可能简单。在下面的代码中,我试图使用多线程来完成它。但是当另一个线程启动时,我无法关闭该线程。我可以在播放 10 秒后关闭视频,但我无法将退出命令移到其他任何地方来关闭其他视频:playSippycup.stdin.write('q')

Here's are the errors I'm currently receiving:

以下是我目前收到的错误:

Unhandled exception in thread started by <function shoppingcart at 0xb6c566f0>Playing Sippycup

Unhandled exception in thread started by <function dodgeballs at 0xb6c56670>
Traceback (most recent call last):
    File "./labmural2.py", line 53, in dodgeballs
    playDodgeballs.stdin.write('q')
NameError: global name 'playDodgeballs' is not defined
Traceback (most recent call last):
  File "./labmural2.py", line 71, in shoppingcart
    playShoppingcart.stdin.write('q')
NameError: global name 'playShoppingcart' is not defined

Thanks so much for any help you guys can offer!

非常感谢你们提供的任何帮助!

#!/usr/bin/env python

import RPi.GPIO as GPIO
import subprocess
import time
import thread

GPIO.setmode (GPIO.BCM)
GPIO.setwarnings (False)

GPIO.setup(9, GPIO.IN)
GPIO.setup(10, GPIO.IN)
GPIO.setup(11, GPIO.IN)

GPIO.setup(17, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
GPIO.setup(27, GPIO.OUT)

def sippycup( name ):

        global playSippycup

        while True:
                if GPIO.input(11) == True:
                        print name
                        time.sleep(1)
                        playSippycup=subprocess.Popen(['omxplayer','Desktop/videos/sippycup.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                        time.sleep(10)
                        playSippycup.stdin.write('q')

                if GPIO.input(9) == True:
                        playSippycup.stdin.write('q')

                if GPIO.input(10) == True:
                        playSippycup.stdin.write('q')

def dodgeballs( name ):

        global playDodgeballs

        while True:
                if GPIO.input(9) == True:
                        print name
                        time.sleep(1)
                        playDodgeballs=subprocess.Popen(['omxplayer','Desktop/videos/dodgeballs.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                        time.sleep(10)
                        playDodgeballs.stdin.write('q')

                if GPIO.input(10) == True:
                        playDodgeballs.stdin.write('q')

                if GPIO.input(11) == True:
                        playDodgeballs.stdin.write('q')

def dodgeballs( name ):

        global playDodgeballs

        while True:
                if GPIO.input(9) == True:
                        print name
                        time.sleep(1)
                        playDodgeballs=subprocess.Popen(['omxplayer','Desktop/videos/dodgeballs.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                        time.sleep(10)
                        playDodgeballs.stdin.write('q')

                if GPIO.input(10) == True:
                        playDodgeballs.stdin.write('q')

                if GPIO.input(11) == True:
                        playDodgeballs.stdin.write('q')

def shoppingcart( name ):

        global playShoppingcart

         while True:
                if GPIO.input(10) == True:
                        print name
                        time.sleep(1)
                        playShoppingcart=subprocess.Popen(['omxplayer','Desktop/videos/shoppingcart.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                        time.sleep(10)
                        playShoppingcart.stdin.write('q')

            if GPIO.input(9) == True:
                        playShoppingcart.stdin.write('q')

            if GPIO.input(11) == True:
                        playShoppingcart.stdin.write('q')

thread.start_new_thread( sippycup, ("Playing Sippycup",) )
thread.start_new_thread( dodgeballs, ("Playing Dodgeballs",) )
thread.start_new_thread( shoppingcart, ("Playing Shoppingcart",) )

while True:
            pass

GPIO.cleanup()


NEW EDIT:

新编辑:

#!/usr/bin/python

from time import sleep
import RPi.GPIO as GPIO
import subprocess
import time
import thread

GPIO.setmode (GPIO.BCM)
GPIO.setwarnings (False)

GPIO.setup(9, GPIO.IN)
GPIO.setup(10, GPIO.IN)
GPIO.setup(11, GPIO.IN)

GPIO.setup(17, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
GPIO.setup(27, GPIO.OUT)

def welcome_loop():
    while True:
            global playProcess
            x = 1
            print "LOOPING"
            time.sleep(.5)
            playProcess=subprocess.Popen(['omxplayer','-b','Desktop/videos/loop/loop.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
            time.sleep(10)
            playProcess.stdin.write('q')
            x += 1

def videos():
    while True:
            if GPIO.input(9):
                    print "STOP LOOP"
                    time.sleep(.5)
                    playProcess.stdin.write('q')
                    time.sleep(.5)
                    print "Play Sippycup"
                    sippycup_video=subprocess.Popen(['omxplayer','-b','Desktop/videos/sippycup.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                    time.sleep(10)
                    sippycup_video.stdin.write('q')
                    time.sleep(.5)
                    welcome_loop()

            if GPIO.input(10):
                    print "STOP LOOP"
                    time.sleep(.5)
                    playProcess.stdin.write('q')
                    time.sleep(.5)
                    print "Play Dodgeballs"
                    dodgeballs_video=subprocess.Popen(['omxplayer','-b','Desktop/videos/dodgeballs.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                    time.sleep(10)
                    dodgeballs_video.stdin.write('q')
                    time.sleep(.5)
                    welcome_loop()

            if GPIO.input(11):
                    print "STOP LOOP"
                    time.sleep(.5)
                    playProcess.stdin.write('q')
                    time.sleep(.5)
                    print "Play Shoppingcart"
                    shoppingcart_video=subprocess.Popen(['omxplayer','-b','Desktop/videos/shoppingcart.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                    time.sleep(10)
                    shoppingcart_video.stdin.write('q')
                    time.sleep(.5)
                    welcome_loop()

thread.start_new_thread( videos, () )
thread.start_new_thread( welcome_loop, () )

while True:
    pass

GPIO.cleanup()

ERROR:

错误:

Unhandled exception in thread started by Traceback (most recent call last): File "./labmural2.py", line 28, in welcome_loop playProcess.stdin.write('q') IOError: [Errno 32] Broken pipe

由 Traceback 启动的线程中未处理的异常(最近一次调用最后一次):文件“./labmural2.py”,第 28 行,在welcome_loop playProcess.stdin.write('q') IOError: [Errno 32] Broken pipe

回答by jfs

NameError: global name 'playDodgeballs' is not definedmeans that you are trying to use playDodgeballsbefore it is defined playDodgeballs = ...

NameError: global name 'playDodgeballs' is not defined意味着您playDodgeballs在定义之前尝试使用playDodgeballs = ..

I would simplify your code by removing all globals and threads. subprocess.Popenruns a separate process; it doesn't block your main thread:

我将通过删除所有全局变量和线程来简化您的代码。subprocess.Popen运行一个单独的进程;它不会阻塞你的主线程:

names = 'sippycup', 'dodgeballs', 'shoppingcart'
movies = ['Desktop/videos/{name}.mp4'.format(name=name) for name in names]
players = [Player(movie=movie) for movie in movies]
player = players[0]

setup_io() # GPIO setup
while True:
    for key in get_key_events(): # get GPIO input
        if key == '0':
           player = players[0]
        elif key == 'space':
           player.toggle() # pause/unpause
        elif key == 'enter':
           player.start()
        ...

where Playeris a simple wrapper around omxplayersubprocess:

子流程Player的简单包装器在哪里omxplayer

import logging
from subprocess import Popen, PIPE, DEVNULL

logger = logging.getLogger(__name__)

class Player:
    def __init__(self, movie):
       self.movie = movie
       self.process = None

    def start(self):
        self.stop()
        self.process = Popen(['omxplayer', self.movie], stdin=PIPE,
                             stdout=DEVNULL, close_fds=True, bufsize=0)
        self.process.stdin.write(start_command) # start playing

    def stop(self):
        p = self.process
        if p is not None:
           try:
               p.stdin.write(quit_command) # send quit command
               p.terminate()
               p.wait() # -> move into background thread if necessary
           except EnvironmentError as e:
               logger.error("can't stop %s: %s", self.movie, e)
           else:
               self.process = None

    def toggle(self):
        p = self.process
        if p is not None:
           try:
               p.stdin.write(toggle_command) # pause/unpause
           except EnvironmentError as e:
               logger.warning("can't toggle %s: %s", self.movie, e)

Specify appropriate start_command, quit_command, toggle_command. You could define different methods depending on what commands omxplayer understands and what commands you need.

指定适当的start_command, quit_command, toggle_command。您可以根据 omxplayer 理解的命令以及您需要的命令定义不同的方法。