質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.34%
Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

1回答

338閲覧

動画再生の切り替え時に現在開いている画面が写ってしまう

BIWD

総合スコア10

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

3クリップ

投稿2025/01/16 03:22

編集2025/01/17 02:39

実現したいこと

現状:動画と動画が切り替わるときに、一度動画ウィンドウが閉じて次の動画に切り替わるので、その一度ウィンドウが閉じた時にデスクトップ(現在開いている画面)が見えてしまう。
→デスクトップを写らない様に改善したいです。

発生している問題・分からないこと

動画の再生プログラム実行中、動画と動画の切り替え時にデスクトップが写ってしまう

エラーメッセージ

error

1エラーメッセージは表示されていません。

該当のソースコード

Python

1import RPi.GPIO as GPIO 2import subprocess 3import time 4import threading 5 6SWITCH_GPIO = 13 7LED_GPIO = 0 8TOGGLE_GPIO = 20 9 10VIDEO_SELECT = "/home/pi/Desktop/AEDファイル/モード切替.mp4" 11VIDEO_ADULT = "/home/pi/Desktop/AEDファイル/小学生~大人.mp4" 12VIDEO_CHILD = "/home/pi/Desktop/AEDファイル/未就学児.mp4" 13VIDEO_3in1 = "/home/pi/Desktop/AEDファイル/3in1.mp4" 14 15GPIO.setwarnings(False) 16GPIO.setmode(GPIO.BCM) 17GPIO.setup(SWITCH_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP) 18GPIO.setup(LED_GPIO, GPIO.OUT) 19GPIO.setup(TOGGLE_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP) 20 21button_pressed = False 22button_process = None 23 24 25def kill_ffplay(): 26 try: 27 subprocess.run(["pkill", "ffplay"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) 28 time.sleep(1) 29 except Exception as e: 30 print(f"Error killing ffplay: {e}") 31 32def play_video(video_path, blocking=True): 33 kill_ffplay() 34 if blocking: 35 subprocess.run([ 36 "ffplay", "-fs", "-noborder", "-autoexit", "-loglevel", "quiet", "-stats", "-analyzeduration", "1", "-probesize", "32", video_path], 37 stdout=subprocess.DEVNULL, 38 stderr=subprocess.DEVNULL 39 ) 40 else: 41 return subprocess.Popen([ 42 "ffplay", "-fs", "-noborder", "-autoexit", "-loglevel", "quiet", "-stats", "-analyzeduration", "1", "-probesize","32", video_path], 43 stdout=subprocess.DEVNULL, 44 stderr=subprocess.DEVNULL 45 ) 46 47def blink_led(): 48 while GPIO.input(SWITCH_GPIO) == GPIO.HIGH: 49 GPIO.output(LED_GPIO, GPIO.HIGH) 50 time.sleep(0.1) 51 GPIO.output(LED_GPIO, GPIO.LOW) 52 time.sleep(0.1) 53 54def monitor_button(): 55 global button_pressed 56 while not button_pressed: 57 if GPIO.input(SWITCH_GPIO) == GPIO.LOW: 58 button_pressed = True 59 GPIO.output(LED_GPIO, GPIO.LOW) 60 break 61 62 63try: 64 65 play_video(VIDEO_SELECT) 66 67 if GPIO.input(TOGGLE_GPIO) == GPIO.HIGH: 68 print("大人用動画") 69 button_process = play_video(VIDEO_ADULT, blocking=False) 70 else: 71 print("子供用動画") 72 button_process = play_video(VIDEO_CHILD, blocking=False) 73 74 button_pressed = False 75 76 time.sleep(55) 77 78 led_thread = threading.Thread(target=blink_led) 79 led_thread.start() 80 81 82 button_thread = threading.Thread(target=monitor_button) 83 button_thread.start() 84 85 led_thread.join() 86 87 if button_process is not None: 88 button_process.kill() 89 90 91 play_video(VIDEO_3in1) 92 93finally: 94 GPIO.cleanup() 95

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

pygameやopencv、vlc-pythonなどを使用して実行してみたのですが、変わりませんでした

補足

RaspberrypiOSを使用しています。Raspberrypi4modelB バージョンbullseye
ThonnyのIDEから実行しています。

meielle_08👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

syoshinsya-

2025/01/16 15:49

「実行中のプログラムコードが写ってしまう」とはどの様に写っているのでしょうか? 記載されているソースコードが全て写っているのですか? また、プログラムの実行方法はどのようにしていますか? 実行環境(ハードウェア構成)や実行方法がわかりません。
BIWD

2025/01/16 23:41

コメントありがとうございます。 自分が少し勘違いしていたのですが、ソースコードが見えてしまう訳ではなく、動画と動画が切り替る時に一度動画ウィンドウが閉じて次の動画に切り替わるので、その1度ウィンドウが閉じた時にデスクトップ(現在開いている画面)が見えてしまう、というとこでした。 環境はthonnyを使用しており、ledライトの着いているスイッチ、オンオフの出来るトグルスイッチをGPIOで繋げています。 ledライト GPIO29 ledライトスイッチ GPIO28 トグルスイッチ GPIO20 です。よろしくお願い致します。
syoshinsya-

2025/01/16 23:42

質問内容としては、動画の再生ウィンドウを閉じずに別の動画の再生を開始したいということですね
BIWD

2025/01/16 23:45

その通りです。 説明不足で申し訳ありませんでした。
syoshinsya-

2025/01/17 00:12

opencvでやるのがいいかなと思います。 opencvの動画再生方法についてはWeb上にたくさんあるので、そこは自分で調べてもらって、躓いた時に質問にその内容を追記してください。 補足としては、現状subprocessによるコマンド実行で再生、pkillによる停止を行っていますが、この場合再生プロセスがなくなり、ウィンドウが閉じてしまうのは避けられません。 opencvについても同様です。 そのためopencv-pythonの使い方を調べて、同じウィンドウで動画再生をするのがよいと思います。
dodox86

2025/01/17 02:09

@質問者 BEWDさん > 自分が少し勘違いしていたのですが、ソースコードが見えてしまう訳ではなく、動画と動画が切り替る時に一度動画ウィンドウが閉じて次の動画に切り替わるので、その1度ウィンドウが閉じ> た時にデスクトップ(現在開いている画面)が見えてしまう、というとこでした。 現状ですと、本質問を眺めた人は少し??となる質問ですね。質問は編集できますので、コメント欄のみだけでなく質問の文を追記、修正されることをお勧めします。 > 環境はthonnyを使用しており、ledライトの着いているスイッチ、オンオフの出来るトグルスイッチをGPIOで繋げています。 とのことですが、Raspberry PiへはGUIでログインして、ThonnyのIDEからご提示のPythonスクリプトを手動で実行している、ということでしょうか。
BIWD

2025/01/17 02:40

返信ありがとうございます。 修正させていただきました。
guest

回答1

0

2つの課題があります

1) 動画切り替え時のラグ

  • video_play 最初の動画再生。終了後 or 一定時間後
  • video_play 次の動画再生。

一旦、他のコードを全部取り除いて
2つの動画の再生を試してみてください。

続けて実行したときに、プロセス終了⇒次のプロセス開始に
ffplay だと 一旦ウィンドウが閉じられるので
どうしても隙間が出来てしまいます。

環境によっては気にならないくらいかもしれませんが、
許容できない場合は、別の動画再生手段が必要です。

⇒ vlc や mpv 等でプレイヤーを一つ生成し、
再生しているメディアを切り替える

opencv は音声がなかったはず。


2) その他の遅延要素。主にブロッキング処理

追記: 次に記載した 動画再生を個別スレッドにする方式にする場合、このセクションはスキップできます。
動画再生を別スレッドで管理すれば、メインでの遅延は影響しない為

裏画面が映ってしまうという事は、
動画再生の合間にある処理で時間がかかっているので、
可能なら、以下のブロッキング処理を取り除けないか検討してみましょう。

  • 続けて実行した場合、task_kill 内で 1秒遅延が入ります。

  taskkill の代替、Popen の戻り値に kill メソッド
選択枝として、次の動画を開始してから前の動画を kill が可能に

  • 2番目の動画が 55秒以内の場合、time.sleep で余分に待たされる。

 ⇒ process.wait(55) で sleep 代替

  • led_thread.join() でスレッドの終了待ち

等の遅延により、次の動画が始まる迄の合間が
問題の状態になっているはずです。

例えば、2つ目の動画は、プロセスオブジェクトの wait と timeout を使うことで
動画が55秒以内でも無駄な待機時間を省けます。

python

1proc = play_video(..., blocking=False) 2try: 3 proc.wait(timeout=55) 4except subprocess.TimeoutExpired: 5 pass 6 7... 8 9if proc.poll(): 10 proc.kill()

if button_process is not None: は恐らく意図通りではないコード。
poll メソッドによりプロセスが稼働中かどうかは判別できます。


解決策: 動画再生のみ個別スレッドにする

ffplay を外部プロセスで呼び出しは、
プロセスの切れ目にどうしても一定のちらつきが発生する為、許容できない場合は

MPV 等で1つのプレイヤーを起動し続け、再生メディアのみ切り替えるアプローチ。
(VLCでも似たような実装は可能なはずです)

動画再生を個別のスレッドで管理することで、
他のGPIOの処理部分のラグの影響と、動画再生の制御を切り離せます。

コードはアイデアを示す断片のみ。

python

1 2import time 3from threading import Thread 4from queue import Queue 5 6 7def video_worker(queue): 8 ## 要準備 9 # - pip install python-mpv 10 # - libmpv 共有ライブラリへの PATH 設定 11 from mpv import MPV 12 13 mpv = MPV(fullscreen=True) 14 15 for cmd, *args in iter(queue.get, None): 16 mpv.command(cmd, *args) 17 mpv.stop() 18 19 20def main(): 21 video_queue = Queue() 22 thread = Thread(target=video_worker, 23 args=(video_queue,), name="video", daemon=True) 24 thread.start() 25 26 video_queue.put(("loadfile", "a.mp4")) 27 time.sleep(10) 28 video_queue.put(("loadfile", "b.mp4")) 29 time.sleep(10) 30 31 video_queue.put(None) # Threadへ終了要求 32 33 34# 汎用性の為に、mpv.command で内部コマンド呼び出し。 35# 例) video_queue.put(("set", "fullscreen", "no")) 36# => mpv.command("set", "fullscreen", "no") 37# 再生メディア切り替えだけであれば、mpv.play(path) でも可能。
  • python-mpv は ctypes で共有ライブラリの関数を呼び出します。
    mpv の実行ファイルではなく、共有ライブラリ libmpv が必要です。
    動作報告はあるけど、ライブラリを使う為の準備が少し手間かも知れない。
    https://github.com/jaseg/python-mpv/issues/154

他の回避策

切り替え時の遅延自体は許容出来て
ターミナル上のコードが映っていること自体が問題であれば、
適当な GUI プログラムを全画面表示で隠すなどの対策は考えられます。

投稿2025/01/17 04:26

編集2025/01/17 04:37
teamikl

総合スコア8791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BIWD

2025/01/17 07:20 編集

回答ありがとうございます。 以下のようにコードを変更してみました。 しかし、mpvのインストールできたのですが、libmpvはバージョンの相違がありうまくインストールができませんでした。 もしご存じでしたら、libmpvのインストールについて詳しく教えていただきたいです。 ↓変更後のコード ```python import RPi.GPIO as GPIO import time import threading from queue import Queue from threading import Thread from mpv import MPV # mpv ライブラリ # GPIO ピン設定 SWITCH_GPIO = 13 LED_GPIO = 0 TOGGLE_GPIO = 20 # 動画パス VIDEO_SELECT = "/home/pi/Desktop/AEDファイル/モード切替.mp4" VIDEO_ADULT = "/home/pi/Desktop/AEDファイル/小学生~大人.mp4" VIDEO_CHILD = "/home/pi/Desktop/AEDファイル/未就学児.mp4" VIDEO_3in1 = "/home/pi/Desktop/AEDファイル/3in1.mp4" # GPIO 初期設定 GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(SWITCH_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(LED_GPIO, GPIO.OUT) GPIO.setup(TOGGLE_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_UP) # グローバル変数 button_pressed = False video_queue = Queue() # mpv ワーカースレッド def video_worker(queue): mpv = MPV(fullscreen=True) for cmd, *args in iter(queue.get, None): mpv.command(cmd, *args) mpv.stop() # LED 点滅スレッド def blink_led(): while not button_pressed: GPIO.output(LED_GPIO, GPIO.HIGH) time.sleep(0.1) GPIO.output(LED_GPIO, GPIO.LOW) time.sleep(0.1) # ボタン監視スレッド def monitor_button(): global button_pressed while not button_pressed: if GPIO.input(SWITCH_GPIO) == GPIO.LOW: # ボタンが押された button_pressed = True GPIO.output(LED_GPIO, GPIO.LOW) # LED を消灯 break try: # mpv スレッド起動 thread = Thread(target=video_worker, args=(video_queue,), daemon=True) thread.start() # モード選択動画再生 video_queue.put(("loadfile", VIDEO_SELECT)) time.sleep(5) # 再生を少し待つ # トグルスイッチで再生動画を選択 if GPIO.input(TOGGLE_GPIO) == GPIO.HIGH: print("大人用動画") video_queue.put(("loadfile", VIDEO_ADULT)) else: print("子供用動画") video_queue.put(("loadfile", VIDEO_CHILD)) # ボタン押下待機 button_pressed = False led_thread = threading.Thread(target=blink_led) led_thread.start() button_thread = threading.Thread(target=monitor_button) button_thread.start() # ボタンが押されるまで待機 button_thread.join() # 3in1 動画再生 video_queue.put(("loadfile", VIDEO_3in1)) finally: GPIO.cleanup() video_queue.put(None) # mpv スレッド終了要求 ```
teamikl

2025/01/17 08:02

回答に記載した URL python-mpv の issue に報告があるようです https://github.com/jaseg/python-mpv/issues/154 URL に記載されてる情報だと この libmpv-dev の部分で共有ライブラリがインストール sudo apt install mpv libmpv-dev python3-mpv バージョン指定が必要な場合は別途 pip で pip install python-mpv<=some_version pip/apt 両方でインストールした場合、 どちらが読み込まれているか混同しないように注意 代案で vlc がつかえるなら、 そちらで同様の実装にしてもいいかもしれません。 player のインスタンスは一つのみにして、set_media で動画切り替え。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.34%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問