mieki256's diary



2021/06/29(火) [n年前の日記]

#2 [love2d] love2dで2つの動画を使って動画の一部を透明に見せかける

RGBA動画を元にして、RGB動画と、アルファチャンネルのみ取り出した白黒のRGB動画を作成することができた。この2つの動画を使って、love2d上で、動画の一部を透明にした感じの描画ができるかどうか試してみる。

念のために書いておくけど、love2d で扱える動画フォーマット ogv (Theora) はアルファチャンネルを含めることができないので、動画の一部を透明にしたい場合、何かしら頓智が必要になるわけで。

環境は、Windows10 x64 20H2 + love2d 11.3。

手順としては、昨日試した通り。

_ogvファイルとアルファチャンネル

再度、流れを書くけど…。 これを、2つの動画を使って行う。

ソースは以下。

_main.lua
function love.load()
  -- load bg image
  bgimg = love.graphics.newImage("bg.jpg")
  
  -- load video(.ogv)
  maskvideo = love.graphics.newVideo("mask.ogv")
  rgbvideo = love.graphics.newVideo("rgb.ogv")
  maskvideo:play()
  rgbvideo:play()
end

function love.update(dt)
end

function love.draw()
  -- loop video play
  if not rgbvideo:isPlaying() then
    maskvideo:rewind()
    rgbvideo:rewind()
    maskvideo:play()
    rgbvideo:play()
  end
  
  -- canvas clear
  love.graphics.clear(0, 0, 0, 1)

  -- draw bg
  love.graphics.setColor(1, 1, 1, 1)
  love.graphics.draw(bgimg, 0, 0)

  -- draw video
  love.graphics.setBlendMode("subtract")
  love.graphics.draw(maskvideo, 0, 0)
  
  love.graphics.setBlendMode("add")
  love.graphics.draw(rgbvideo, 0, 0)

  -- draw text
  love.graphics.setBlendMode("alpha")
  love.graphics.setColor(1, 1, 1, 1)
  love.graphics.print("ESC to exit.", 8, 4)
end

function love.keypressed(key, scancode, isrepeat)
  if key == "escape" then
    love.event.quit()
  end
end

_conf.lua
function love.conf(t)
  t.window.width = 1280
  t.window.height = 720
  t.window.title = "Draw video alpha"
  t.window.fullscreen = false
  -- t.window.fullscreentype = "exclusive"
end

必要な画像、動画は以下。

_bg.jpg
_mask.ogv
_rgb.ogv

念のために、ソース、画像、動画をまとめてzipにして置いときます。

_draw_video_alpha.zip

さて。実行してみたら、こうなった。



一見すると上手く行ってるように思えたけれど、よく観察してみると、どうも周辺に残像のようなものがチラチラと表示される…。

デスクトップを60fpsでキャプチャして、一部分をクロップして4fpsにしてみた。



アルファチャンネル担当の動画と、RGB動画の、同期が取れていないようだなと…。RGB動画のほうが1フレーム遅れて描画される瞬間が何度も発生しているように見える。それで輪郭がチラチラするというか、残像のようなものが見えてしまう模様。

ちなみに、元動画がそもそも1フレームずれているのではないかと疑って、AviUtl + 拡張編集プラグインを使って、2つの動画を重ねて確認してみたけれど、元動画はずれてるように見えなかった。というか、24fpsの動画で1フレームずれていたら、こんなもんじゃ済まない。もっと盛大なずれになる。つまりコレは、love2dで再生・描画した際に、love2dのフレームレートで、1フレームずれる時がある、ということだろう…。

解決策はあるのだろうか…。

そもそも love2dは、再生される動画は1つ、という前提で作られてそうな気もする。フツー、2つの動画を、両方一度に再生するとは思わないよな…。

1つの動画にしてみる。 :

2つの動画を同時に再生して同期が取れてないのが問題なら、1つの動画にまとめてしまえばいいのではないかと思いついた。

つまり、以下のような見た目になっている、1つの動画にしてしまえば…。

comb_frame.png

これを、以下のような仕組みで利用する。

draw_video_alpha2_about.png

これなら動画の同期云々なんて考えなくてもよいのではないか。

試してみた。ソースは以下。

_main.lua
function love.load()
  videocanvas = love.graphics.newCanvas(1280, 1440)
  
  -- load bg image
  bgimg = love.graphics.newImage("bg.jpg")
  
  -- load video(.ogv)
  video = love.graphics.newVideo("comb.ogv")
  video:play()
end

function love.update(dt)
end

function love.draw()
  -- loop video play
  if not video:isPlaying() then
    video:rewind()
    video:play()
  end
  
  -- canvas clear
  love.graphics.clear(0, 0, 0, 1)

  -- draw bg
  love.graphics.setBlendMode("alpha")
  love.graphics.setColor(1, 1, 1, 1)
  love.graphics.draw(bgimg, 0, 0)
  
  -- draw video to video canvas
  love.graphics.setCanvas(videocanvas)
  love.graphics.draw(video, 0, 0)
  love.graphics.setCanvas()

  -- draw video canvas
  love.graphics.setBlendMode("subtract")
  love.graphics.draw(videocanvas, 0, 0)
  
  love.graphics.setBlendMode("add")
  love.graphics.draw(videocanvas, 0, -720)

  -- draw text
  love.graphics.setBlendMode("alpha")
  love.graphics.setColor(1, 1, 1, 1)
  love.graphics.print("ESC to exit.", 8, 4)
  
end

function love.keypressed(key, scancode, isrepeat)
  if key == "escape" then
    love.event.quit()
  end
end

_conf.lua
function love.conf(t)
  t.window.width = 1280
  t.window.height = 720
  t.window.title = "Draw video alpha2"
  t.window.fullscreen = false
  -- t.window.fullscreentype = "exclusive"
end

動作に必要な画像、動画は以下。

_bg.jpg
_comb.ogv

実行してみたら、こうなった。



一部をクロップして4fpsで再生してみる。



これで上手く行ったのではなかろうか。

ということで、love2d上で疑似的に、アルファチャンネルを持ってるかのような見た目で動画再生することも一応できる、と分かった。

考えてみたら、こういう見た目の素材をどこかで見たなと…。紙芝居ゲームの制作ツールで、こういう画像を用意せよと要求してくる事例があったような…。そのやり方を動画にも流用できるよ、という話になるのかな。

ちなみに、RGB動画とアルファチャンネル動画を上下に並べた動画を作成する作業には、AviUtl + 拡張編集プラグインを使った。ただ、その後ググってみたら、ffmpeg でも上下に繋げた動画を作成できたらしい。

_研究で使うFFmpegコマンドまとめ - Qiita

ffmpeg -i mask.avi -i rgb.avi -filter_complex "vstack" -vcodec utvideo out.avi

入力動画ファイルを2つ指定して、-filter_complex "vstack" を指定すればいいようだなと…。

以上です。

過去ログ表示

Prev - 2021/06 - Next
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project