Покадровое воспроизведение / остановка видеофайла, в ткинтер - PullRequest
0 голосов
/ 12 марта 2019

Я пытаюсь запустить / остановить видеофайл в tkinter на Raspberry Pi, используя python 3.

Мне нужно, чтобы видео запускалось с самого начала каждый раз, когда инфракрасный датчик НИЗКИЙ (сломан) иостановитесь, как только датчик снова станет ВЫСОКИМ.В идеале видео должно быть внутри холста tkinter, чтобы я мог одновременно отображать другие элементы на экране (например, панель загрузки).

Мне удалось запустить все, кроме видео, которое запускаетсякак только датчик обнаружен, но он останавливает все другие процессы (например, полосу загрузки) и не останавливается, когда датчик ВЫСОКИЙ.

здесь приведена упрощенная (и непроверенная) версия кодадля вас вы получите представление об общей структуре (реальный код намного длиннее):

import tkinter as TK
import RPi.GPIO as GPIO
import os

GPIO.setmode(GPIO.BCM)
GPIO.setup(14, GPIO.IN)

class App:
    def __init__(self, root):
        self.root = root
        self.root.config(background = 'black', cursor = 'none')
        self.background = TK.Canvas(root, width = 1024, height = 600, bg = 'black')
        self.background.pack()

        self.ext = 0
        self.trial = 0
        self.infrared()

    def infrared(self):
        if (GPIO.input(14) == False):
            self.makebar()

            if (self.ext == 0):
                self.runvideo()

        else:
            os.system("killall omxplayer.bin")
            self.ext = 0

        self.root.after(16, self.infrared)

    def runvideo(self):
        os.system("omxplayer /home/pi/Desktop/testvideo.m4v")

    def makebar():
        self.stimulus_rect = TK.Canvas(root, width = 1024, height = 50, bg= 'white')
            if self.ext < 1000
                self.ext = self.ext + 10
                self.stimulus_rect.create_rectangle(0, 0, self.ext, 50, fill="red")
                self.stimulus_rect.place(x=0, y=0, anchor="new")
            else:
                self.trial = self.trial + 1
                self.ext = 0

root = TK.Tk()
App(root)
root.mainloop()

Из того, что я смог найти в Интернете: 1) tkinter может быть связан с opencv для достижения этой цели, ноне похоже, что установка opencv на raspberry pi - простая операция;2) В общем, варианты, включающие «os», как представляется, обречены на неудачу в том, чего я хочу достичь.

Я не мог найти чистый способ сделать это.Моим сценарием мечты было бы загружать на холст видеокадры один за другим и делать это с частотой 60 Гц (частота экрана).Затем я проверил бы датчик на той же частоте и предотвратил бы загрузку следующего кадра, если датчик не сломан.В псевдокоде это будет выглядеть так:

def infrared(self):
    if (GPIO.input(14) == False):
        self.makebar()

        if (self.ext == 0):
            self.runvideo()

    else:
        self.video.stop
        self.ext = 0
        self.frame = 0

    self.root.after(16, self.infrared)

def runvideo(self):
    self.frame = self.frame + 1
    video.run("testvideo.m4v", self.frame)

Есть идеи, как этого добиться в tkinter на малиновом пи?

спасибо, муравей

1 Ответ

0 голосов
/ 25 марта 2019

После недели исследований, проб и ошибок вот как я в настоящее время достигаю того, что мне нужно (в псевдокоде):

#### PSEUDOCODE ####         
from subprocess import Popen  # this library is used to open the video file


class App:
    def __init__(self, root):
        self.moviestart = False

    self.movieduration = 130000
    self.movie = "/home/pi/Desktop/test.mp4"

    def infrared(self):
        if (GPIO.input(IR) == False):
            if not self.moviestart:
                self.makevideo()  # Call the function to start the video
            self.moviestart = True  # Flag that the video has started
            self.moviestop = False  # Flag that the video is currently playing
            self.root.after(self.videoduration,
                            self.stopvideo)  # manually call the stop video function 
            # to stop the video after 13 seconds (video's length). 
            # I could not find a more elegant way of doing this, unfortunately. 
        else:
            self.clear_screen()

    self.root.after(self.refreshIR, self.infrared)


def makevideo(self):
    # popen will open the movie in a window of the size I specified, 
    # so that other element from tkinter can be placed on top of the movie window
    omxc = Popen(['omxplayer', self.movie, '--win', "0 30 800 450"])


def stopvideo(self):
    self.moviestart = False  # flag that movie has been stopped       
    if (self.moviestop == False):  # check if the movie is currently playing
        try:  # this is a cheap workaround other problems I had, do not try this at home
            os.system('killall omxplayer.bin')  # this literally kills any omxplayer instance 
            # currently open
            self.moviestop = True  # flag that the movie is not playing at the moment 
        except:
            pass

Надеюсь, это может пригодиться кому-либо еще с похожими проблемами. Я обновлю ответ, если найду лучшее решение. Пока это работает достаточно хорошо.

...