2017-06-25 12 views
1

AVbinがインストールされています。 .wavファイルと.mp3ファイルの両方が動作します。ピグレット、すべての音が鳴った後に終了

import pyglet 

music = pyglet.media.load('A.mp3') 
music.play() 

player = pyglet.media.Player() 
player.queue(pyglet.media.load('B.mp3')) 
player.queue(pyglet.media.load('C.wav')) 

player.play() 


pyglet.app.run() 

pyglet.app.exit() 


私が演じているプログラムを作成したいが、その後、その後、BとCとのキューを果たし、最終的にはすべての3つのサウンドを再生した後に終了します。

私は上記のコードを試しましたが、this投稿によると、 "app.run()は終わりのないループなので、これは[単なる]です。"


3つのサウンドが再生された後、プログラムが終了するように、どのように私は私の最小限のコードを変更することができますか?

ボーナスが、プログラムが一度に2つ(またはそれ以上)の音声ファイル、E.mp3とF.mp3を、再生することができるようにどのように私は私の最小限のコードを変更することができますか?


ありがとう!

答えて

1

あなたが求めていることは、あなたが思うほど単純ではないためです。
例を読みにくくすることなく、できるだけ多くのコメントでコード例をまとめました。コードの下

、私は可能な限り詳細にいくつかの重要な機能を説明してみましょう。

import pyglet 
from pyglet.gl import * 
from collections import OrderedDict 

key = pyglet.window.key 

class main(pyglet.window.Window): 
    def __init__ (self, width=800, height=600, fps=False, *args, **kwargs): 
     super(main, self).__init__(width, height, *args, **kwargs) 

     self.keys = OrderedDict() # This just keeps track of which keys we're holding down. In case we want to do repeated input. 
     self.alive = 1 # And as long as this is True, we'll keep on rendering. 

     ## Add more songs to the list, either here, via input() from the console or on_key_ress() function below. 
     self.songs = ['A.wav', 'B.wav', 'C.wav'] 
     self.song_pool = None 

     self.player = pyglet.media.Player() 
     for song in self.songs: 
      media = pyglet.media.load(song) 
      if self.song_pool is None: 
       ## == if the Song Pool hasn't been setup, 
       ## we'll set one up. Because we need to know the audio_format() 
       ## we can't really set it up in advance (consists more information than just 'mp3' or 'wav') 
       self.song_pool = pyglet.media.SourceGroup(media.audio_format, None) 
      ## == Queue the media into the song pool. 
      self.song_pool.queue(pyglet.media.load(song)) 

     ## == And then, queue the song_pool into the player. 
     ## We do this because SourceGroup (song_pool) as a function called 
     ## .has_next() which we'll require later on. 
     self.player.queue(self.song_pool) 
     ## == Normally, you would do self.player.eos_action = self.function() 
     ## But for whatever fucky windows reasons, this doesn't work for me in testing. 
     ## So below is a manual workaround that works about as good. 

     self.current_track = pyglet.text.Label('', x=width/2, y=height/2+50, anchor_x='center', anchor_y='center') 
     self.current_time = pyglet.text.Label('', x=width/2, y=height/2-50, anchor_x='center', anchor_y='center') 


    def on_draw(self): 
     self.render() 

    def on_close(self): 
     self.alive = 0 

    def on_key_release(self, symbol, modifiers): 
     try: 
      del self.keys[symbol] 
     except: 
      pass 

    def on_key_press(self, symbol, modifiers): 
     if symbol == key.ESCAPE: # [ESC] 
      self.alive = 0 

     elif symbol == key.SPACE: 
      if self.player.playing: 
       self.player.pause() 
      else: 
       self.player.play() 

     elif symbol == key.RIGHT: 
      self.player.seek(self.player.time + 15) 

     ## == You could check the user input here, 
     ## and add more songs via the keyboard here. 
     ## For as long as self.song_pool has tracks, 
     ## this player will continue to play. 

     self.keys[symbol] = True 

    def end_of_tracks(self, *args, **kwargs): 
     self.alive=0 

    def render(self): 
     ## Clear the screen 
     self.clear() 

     ## == You could show some video, image or text here while the music plays. 
     ## I'll drop in a example where the current Track Name and time are playing. 

     ## == Grab the media_info (if any, otherwise this returns None) 
     media_info = self.player.source.info 
     if not media_info: 
      ## == if there were no meta-data, we'll show the file-name instead: 
      media_info = self.player.source._file.name 
     else: 
      ## == But if we got meta data, we'll show "Artist - Track Title" 
      media_info = media_info.author + ' - ' + media_info.title 

     self.current_track.text = media_info 
     self.current_track.draw() 

     ## == This part exists of two things, 
     ## 1. Grab the Current Time Stamp and the Song Duration. 
     ## Check if the song_pool() is at it's end, and if the track Cur>=Max -> We'll quit. 
     ## * (This is the manual workaround) 
     cur_t, end_t = int(self.player.time), int(self.player.source._get_duration()) 
     if self.song_pool.has_next() is False and cur_t >= end_t: 
      self.alive=False 

     ## 2. Show the current time and maximum time in seconds to the user. 
     self.current_time.text = str(cur_t)+'/'+str(end_t) + 'seconds' 
     self.current_time.draw() 

     ## This "renders" the graphics: 
     self.flip() 

    def run(self): 
     while self.alive == 1: 
      self.render() 

      # -----------> This is key <---------- 
      # This is what replaces pyglet.app.run() 
      # but is required for the GUI to not freeze 
      # 
      event = self.dispatch_events() 

x = main() 
x.run() 

通常、あなたは、多くの機能であなたの道を飾るでしょう。 しかし、私はサブクラス化したいとOOPの任意のグラフィカルライブラリを介して、それは非常に厄介な非常に速くなるので。

ので、代わりのpyglet.app.run()は、私はカスタムメイドrun()機能を持っています。
これは、ほとんどの場合、pyglet.app.run()を模倣しています。少なくとも行くことができます。

player.eos_*イベントは壊れているように見えるので。
曲の再生が完了したかどうかを確認する方法のマニュアルを追加しました。

これは、トラック継続時間を返しself.song_poolpyglet.media.SourceGroupself.player.timepyglet.media.player.timeself.player.source._get_duration()の組み合わせです。

SourceGroupは、待機中の曲の最後にいるかどうかを示すhas_next()機能を提供します。他の2つの変数は、現在のトラックの終わりに達したかどうかを示します。これが終了するかどうかを決定するために必要なのはこれだけです。

今、私は技術的に追加の曲を追加する方法を追加していません。もう一度、それはあなたが思うよりも難しいでしょうから。たとえばif symbol == key.LCTRL: self.song_pool.queue(pyglet.media.load(input('Song: ')))を選択しない限りしかしもう一度、あなたがする必要があるのは、self.song_poolキューに曲を追加することです。

これがあなたの質問に答えることを願っています。ボーナス1つ。

+0

+1このサンプルコードはありがとうございます。私も同様の問題を抱えていましたが、今度はビデオで。レンダリングループを止めるトリックで、すべてが今動作します(mp4ビデオを除いて...しかし、これはAVbinの問題です)。 –

+1

ちょうど言及に.... pyglet 1.4.0a1はAVbinからffmpegに移動しました、そして今、mp4といくつかの他のフォーマットがpyglet Playerとうまく動作しています! –

関連する問題