主にプログラミングに関して。Python, .NET Framework(C#), JavaScript, その他いくらか。
記事にあるサンプルやコードは要検証。使用に際しては責任を負いかねます

スポンサーサイト

                
tags:
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

.NET FrameworkのStoryboardを使ったMediaElementの再生管理

                
 WPFStoryboardを使うと、MediaElementの再生や停止のタイミングを管理できる。

 MediaElementにはMediaEndedというメディア再生終了を捕捉するイベントハンドラがあるが、イベント発生が再生終了時なので、これを使ってもソースファイルの切り替えのために、シームレスに音楽ファイルを連続再生することができない。そんなわけでソースファイル切り替えの代替手段として、Storyboardを使って、音楽ファイルの切り替えがシームレスな再生ができるか試してみた。

 結果は2曲間のシームレスな再生ができたと思いきや、Seekを使って2曲間の直前に時間をもどして検証しなおすとギャップが入った。そこでまた検証のために直前にもどすとシームレスな再生で、また検証のためにもどすと今度はギャップが……という繰り返し。安定してシームレスで再生されることはなく、なぜかギャップ入り再生とシームレス再生が交互に繰り返された。交互なのだからこの法則から何か見出したかったが、結局なぜだかわからない。

 とりあえずまた別の方法を探すか……

import sys, clr, wpf
sys.path.append('Lib')

import System, System.IO
from System import Windows, TimeSpan
from System.Windows import Window, Controls, Thickness, Threading, Media

class Window1 (Window):
def __init__(self):
wpf.LoadComponent(self, 'Window1.xaml')
self.grid1 = self.FindName("hoge")
self.mediaBox = self.FindName("mediaBox")
self.button2 = self.FindName("button2")
##self.story = self.FindName("story")
self.story = Media.Animation.Storyboard()
self.buttonSeek = self.FindName("buttonSeek")

self.volume = 0.3

self.files = [r"C:\Users\h\Music\Linkin Park\A Thousand Suns\01 The Requiem.wma",
r"C:\Users\h\Music\Linkin Park\A Thousand Suns\02 The Radiance.wma",
r"C:\Users\h\Music\Linkin Park\A Thousand Suns\03 Burning in the Skies.wma",
r"C:\Users\h\Music\Linkin Park\A Thousand Suns\04 Empty Spaces.wma",
r"C:\Users\h\Music\Linkin Park\A Thousand Suns\05 When They Come for Me.wma",
r"C:\Users\h\Music\Linkin Park\A Thousand Suns\06 Robot Boy.wma",
r"C:\Users\h\Music\Linkin Park\A Thousand Suns\07 Jornada del Muerto.wma",
]

def load(self, target, e):
self.delay_time = 0.0
self.li_media = []
self.dic_media = {}
self.time_collection = []
for num,file in enumerate(self.files):
mediaEl = Controls.MediaElement()
mediaEl.LoadedBehavior = System.Windows.Controls.MediaState.Stop
mediaEl.Name = "m%02d" %(num)
mediaEl.Source = System.Uri(file)
mediaEl.Volume = 0.2
mediaEl.MediaOpened += self.add2storyboard(mediaEl)
self.mediaBox.AddChild(mediaEl)
self.RegisterName(mediaEl.Name, mediaEl)
print mediaEl.Name

def add2storyboard(self, el):
def inner(target, e):
self.li_media.append(el.Name)
if len(self.li_media) != len(self.files):
return False
self.li_media.sort()
for name in self.li_media:
elm = self.FindName(name)
print elm.NaturalDuration.TimeSpan.TotalSeconds
mediaTimeline = Media.MediaTimeline()
mediaTimeline.Name = "s" + elm.Name
mediaTimeline.Source = elm.Source
mediaTimeline.BeginTime = TimeSpan(0, 0, 0, 0, self.delay_time)
mediaTimeline.Duration = elm.NaturalDuration
self.time_collection.append(self.delay_time)
self.delay_time += elm.NaturalDuration.TimeSpan.TotalMilliseconds
self.story.SetTargetName(mediaTimeline, elm.Name)
self.story.AddChild(mediaTimeline)
self.dic_media.update({elm.Name:{"begin":mediaTimeline.BeginTime,
"dur":self.delay_time}})
return inner


self.media1 = self.FindName("media1")
self.media1.Volume = 0.3
self.media2 = self.FindName("media2")
self.media2.Volume = 0.3

def play(self, target, e):
self.story.Begin(self, True)

def seek(self, target, e):
print "seek"
self.story.Pause(self)
self.story.Seek(self, TimeSpan(0, 0, 0, 110), Media.Animation.TimeSeekOrigin.BeginTime)
self.story.Resume(self)

def rewind(self, target, e):
t = self.story.GetCurrentTime(self).TotalMilliseconds
print t
for p in range(len(self.time_collection) - 1):
print self.time_collection[p], t, self.time_collection[p + 1]
if self.time_collection[p] <= t < self.time_collection[p] + 2000:
print 1
if p > 0:
self.story.SeekAlignedToLastTick(self, TimeSpan(0, 0, 0, 0, self.time_collection[p - 1] + 1), Media.Animation.TimeSeekOrigin.BeginTime)
return False
else:
self.story.SeekAlignedToLastTick(self, TimeSpan(0, 0, 0, 0, self.time_collection[0] + 1), Media.Animation.TimeSeekOrigin.BeginTime)
return False
elif self.time_collection[p] <= t < self.time_collection[p + 1]:
print 2
self.story.SeekAlignedToLastTick(self, TimeSpan(0, 0, 0, 0, self.time_collection[p] + 1), Media.Animation.TimeSeekOrigin.BeginTime)
return False
print 3
if self.time_collection[p + 1] <= t < self.time_collection[p + 1] + 2000:
print 3.1, self.time_collection[p]
self.story.SeekAlignedToLastTick(self, TimeSpan(0, 0, 0, 0, self.time_collection[p] + 1), Media.Animation.TimeSeekOrigin.BeginTime)
self.story.Resume(self)
return False
else:
print 3.2, self.time_collection[p + 1]
self.story.SeekAlignedToLastTick(self, TimeSpan(0, 0, 0, 0, self.time_collection[p + 1] + 1), Media.Animation.TimeSeekOrigin.BeginTime)
self.story.Resume(self)
return False

def forward(self, target, e):
t = self.story.GetCurrentTime(self).TotalMilliseconds
print t
for begin in self.time_collection:
if t < begin:
self.story.SeekAlignedToLastTick(self, TimeSpan(0, 0, 0, 0, begin + 1), Media.Animation.TimeSeekOrigin.BeginTime)
return True
return False

def volume(self):
return str(self.volume)


<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="wpf"
Height="500"
Width="300">
<StackPanel Name="hoge">
<StackPanel Name="mediaBox">
<Button Name="button" Content="Push" Width="50" Height="50" Click="play"/>
<Button Name="button2" Content="Pause" Width="50" Height="50"/>
<Button Name="buttonLoad" Content="Load" Width="50" Height="50" Click="load"/>
<Button Name="buttonSeek" Content="seek" Width="50" Height="50" Click="seek"/>
<Button Name="buttonRewind" Content="re" Width="50" Height="50" Click="rewind"/>
<Button Name="buttonForward" Content="fw" Width="50" Height="50" Click="forward"/>
</StackPanel>
</StackPanel>
</Window>


import wpf

from System.Windows import Application
from Window1 import Window1

window = Window1()
app = Application()
app.Run(window)
            

コメントの投稿

非公開コメント

プロフィール

hMatoba

Author:hMatoba
Github

最新記事
リンク
作ったものなど
月別アーカイブ
カテゴリ
タグリスト

検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。