Go言語 GUIアプリ Fyneへの動画表示
先日Fyneを使用して簡単なGUIアプリを作成しました。
elsammit-beginnerblg.hatenablog.com
今回はFyneを利用して動画を表示・再生させるアプリを作成していこうと思います!!
■環境
・OS:Ubuntu20.04(virtualBox上)
※すでにFyneがインストールされていることを前提にします。
■Fyneへの画像表示
動画表示・再生を行う前にまずは画像の表示を行っていきます。
コードはこんな感じ。
package main import ( "fmt" "fyne.io/fyne/app" "fyne.io/fyne/canvas" "fyne.io/fyne/widget" "gocv.io/x/gocv" "image" ) func main() { Flg = false fileName := "ファイルパス" img := gocv.IMRead(fileName, -1) gocv.Resize(img, &img, image.Point{250, 250}, 0, 0, gocv.InterpolationDefault) imgD, _ := img.ToImage() myApp := app.New() w := myApp.NewWindow("Image") ShowImg := canvas.NewImageFromImage(imgD) ShowImg.FillMode = canvas.ImageFillOriginal label := widget.NewLabel("Show image") w.SetContent(widget.NewVBox( ShowImg, label, )) w.ShowAndRun() }
やっていることは、
opencvで画像データを読み出す。
img := gocv.IMRead(fileName, -1) gocv.Resize(img, &img, image.Point{250, 250}, 0, 0, gocv.InterpolationDefault)
画像表示用画像イメージに変換。
imgD, _ := img.ToImage()
用意したcanvasの上に読み出した画像データをセット。
ShowImg := canvas.NewImageFromImage(imgD) ShowImg.FillMode = canvas.ImageFillOriginal
最後にGUIとしてレイアウトを決めて、
w.SetContent(widget.NewVBox( ShowImg, label, ))
画面表示、
w.ShowAndRun()
になります。
今回画像をこちらとした場合、
先ほどのコードを実行するとこちらのアプリが表示されます。
■動画表示
では本題の動画を表示させます。
全体のコードはこちらになります。
package main import ( "fyne.io/fyne/app" "fyne.io/fyne/canvas" "fyne.io/fyne/widget" "gocv.io/x/gocv" "image" "time" ) func MakeMovie(ShowImg *canvas.Image) { movie, _ := gocv.OpenVideoCapture("再生させる動画パス") img := gocv.NewMat() imgDD, _ := img.ToImage() for { movie.Read(&img) gocv.Resize(img, &img, image.Point{250, 250}, 0, 0, gocv.InterpolationDefault) imgDD, _ = img.ToImage() ShowImg.Image = imgDD canvas.Refresh(ShowImg) time.Sleep(time.Millisecond * 33) } } func main() { fileName := "lena.jpg" img := gocv.IMRead(fileName, -1) gocv.Resize(img, &img, image.Point{250, 250}, 0, 0, gocv.InterpolationDefault) imgD, _ := img.ToImage() myApp := app.New() w := myApp.NewWindow("Image") ShowImg := canvas.NewImageFromImage(imgD) ShowImg.FillMode = canvas.ImageFillOriginal label := widget.NewLabel("Show Movie") go MakeMovie(ShowImg) w.SetContent(widget.NewVBox( ShowImg, label, )) w.ShowAndRun() }
先ほどの画像表示と異なる点は、
func MakeMovie(ShowImg *canvas.Image) { movie, _ := gocv.OpenVideoCapture("再生させる動画パス") img := gocv.NewMat() imgDD, _ := img.ToImage() for { movie.Read(&img) gocv.Resize(img, &img, image.Point{250, 250}, 0, 0, gocv.InterpolationDefault) imgDD, _ = img.ToImage() ShowImg.Image = imgDD canvas.Refresh(ShowImg) time.Sleep(time.Millisecond * 33) } }
を追加して、
go MakeMovie(ShowImg)
により並列処理を行っている点です。
MakeMovie関数ですが、
引数に用意した*canvas.Imageを渡し、
動画の1フレーム毎に取得、canvas.Imageにセットする
処理を行っております。
先ほどの画像と同様、canvasへセットするために読みとったフレーム画像は
imgDD, _ = img.ToImage()
より変換を行っております。
最後に!!
毎回フレーム画像をリフレッシュしないと反映されないので必ずこちらの関数を用いてください。
canvas.Refresh(ShowImg)
では、実際にこちらのコードを用いて、動画を再生してみます!!
実行するとこんな感じで再生されます。
■再生・停止ボタン追加(おまけ)
おまけとして、再生・停止ボタンを用意して動画の停止・再開の機能を追加したいと思います。
コードはこちらになります。
package main import ( "fmt" "fyne.io/fyne/app" "fyne.io/fyne/canvas" "fyne.io/fyne/widget" "gocv.io/x/gocv" "image" "time" ) var Flg bool func MakeMovie(ShowImg *canvas.Image) { Movie, _ := gocv.OpenVideoCapture("./Underwater - 37712.mp4") img := gocv.NewMat() imgDD, _ := img.ToImage() for { if Flg == true { Movie.Read(&img) gocv.Resize(img, &img, image.Point{250, 250}, 0, 0, gocv.InterpolationDefault) imgDD, _ = img.ToImage() ShowImg.Image = imgDD canvas.Refresh(ShowImg) time.Sleep(time.Millisecond * 33) } else { time.Sleep(time.Second) } } } func main() { Flg = false fileName := "lena.jpg" img := gocv.IMRead(fileName, -1) gocv.Resize(img, &img, image.Point{250, 250}, 0, 0, gocv.InterpolationDefault) imgD, _ := img.ToImage() myApp := app.New() w := myApp.NewWindow("Image") ShowImg := canvas.NewImageFromImage(imgD) ShowImg.FillMode = canvas.ImageFillOriginal label := widget.NewLabel("Show Movie") go MakeMovie(ShowImg) var button *widget.Button button = widget.NewButton("Start", func() { label.SetText("Welcome") fmt.Println("push Button") if Flg == true { button.SetText("Start") Flg = false } else { button.SetText("Stop") Flg = true } }) w.SetContent(widget.NewVBox( ShowImg, label, button, )) w.ShowAndRun() }
追加しているのはStart/Stopフラグのみ(のはず)。
こちらを実行するとこちらのようになります!!