何の変哲もないアプリで遅くなりましたが公開いたします!
サムネもなんとなくYouTube風。
VTuberって、最近では手軽に参入できるアプリが出来はじめたものの、自分オリジナルのキャラを使いたい!と思うとすごーく手間がかかるってイメージですよね。
まずキャラクターをデザインして…
3Dだったらモデリングして、モーションキャプチャーして…
2Dでもグラフィックを細かくパーツ分けして…
配信を賑やかにしたいけどちょっとそこまでは厳しい…って思いながらひそかにバーチャルアバター配信を見て(最低限どんな動作があればぎりぎりそれっぽく見えるのか)研究しつつ、考えたものがこちら。
『なんちゃってVTuber』基本仕様
・2Dイラストのみ対応
・一定時間ごとにイラストが目パチ(瞬き)する
・マイク入力に合わせて口パクする
これだけ。カメラも使わない音声検知だけ簡単なんちゃってVTuber!
なんか…どっかで見たような絵面だなと思ってたらゆっくりだこれ。
…これでVTuberなんて言ったらファンに怒られますかね?
でもやっぱり、自分の動画内でキャラクターが反応してくれるって面白いね…口パクと目パチだけでだいぶ印象違う。リアルタイム感が出た気がします。
技術的な話。
動作ツールはPython、使用した画像も顔のベース、目と口それぞれ二種、目と口より上に来るパーツの透明情報入り画像たった6枚だけ。
ウィンドウ画面表示に関しては、
OpenCVを使うかPygameにするか悩んだのですが、FPSの調整とかがやりやすそうだなと思いPygameを使用。
将来的に凝った画像加工や認識を使いたいならOpenCVにする方がいいかもしれない。
というか今の仕様なら画像の透明部分重ねて表示できればなんでもいい。
音声認識に関してはこちらを参考にしました。
qiita.com
基本的な流れとしては、Pygameの1ループに一回音声を検知して、入力があったら画像を切り替えるだけの雑な設定。
※当ソースコードを用いて発生した問題について、管理人は責任を負いかねます。ご了承ください。
使い方
1. Pythonを実行できる環境を作る
2. ソースコードを適当な名前.pyで保存
3. 画像を同じフォルダに置く
4. コマンドプロンプトを起動し、ファイルを置いたディレクトリにcdで移動し『python ファイル名』で実行
画像の構造は、
base.png
kami.png
kuti.png
kuti2.png
me.png
me2.png
me3.png
こんな感じで重ね合わせる前提で細かくパーツ分けされてますが、ちょっとソースいじったら通常ととじ目、口開けの3枚だけでも
何とかなると思います。
これなら、https://character-nantoka.appspot.comとかの画像も使えますね。
今回画像については将来機能拡張することを考えていますので、細かめに。
ソースコード
import pygame from pygame.locals import * import sys import pyaudio import numpy as np #---------------- # pygame初期化 #---------------- pygame.init() screen = pygame.display.set_mode((500,500)) pygame.display.set_caption("VTuber?") #---------------- # 画像取得 #---------------- #基本 bg = pygame.image.load("base.png").convert_alpha() image_rect = bg.get_rect() #目 me1 = pygame.image.load("me.png").convert_alpha() me2 = pygame.image.load("me2.png").convert_alpha() me3 = pygame.image.load("me3.png").convert_alpha() #口 kuti1 = pygame.image.load("kuti.png").convert_alpha() kuti2 = pygame.image.load("kuti2.png").convert_alpha() #髪 kami = pygame.image.load("kami.png").convert_alpha() #フォント font = pygame.font.Font(None, 20) def main(): #---------------- # pyaudio初期化 #---------------- chunk = 1024 FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 44100 p = pyaudio.PyAudio() stream = p.open(format = FORMAT,channels = CHANNELS, rate = RATE, input = True, frames_per_buffer = chunk) #---------------- # 変数設定 #---------------- #タイマー変数 Timer = 0 # 閾値 threshold = 0.025 #描画周期設定 Clock = pygame.time.Clock() FPS = 30 #---------------- # メインループ #---------------- while(1): pygame.display.update() # 音データの取得 data = stream.read(chunk) # ndarrayに変換 x = np.frombuffer(data, dtype="int16") / 32768.0 #時間経過 Timer = pygame.time.get_ticks() # イベント処理 for event in pygame.event.get(): # 閉じるボタンが押されたときの処理 if event.type == QUIT: stream.close() p.terminate() pygame.quit() sys.exit() # 画像生成 ImageOut(screen, image_rect, bg, Select_Eye(Timer), Select_mouse(x, threshold), Select_Add()) #デバッグ用 #DebugGraph(screen, Timer) pygame.display.flip() Clock.tick(FPS) #画面更新 #---------------- # パーツ選択 #---------------- def Select_Eye(Timer): # 瞬き(力技。。。もうちょい自然な見せ方があるはず if ((Timer % 2100) <= 160): put_me = me2 #目(閉じ)描画 else: put_me = me1 #目描画 #キー押下によって目の描画オブジェクトを変更する pressed_key = pygame.key.get_pressed() if pressed_key[K_q]: put_me = me3 #目(><)描画 return put_me def Select_mouse(x, threshold): #音声認識によって口の描画オブジェクトを変更する if x.max() > threshold: put_kuti = kuti1 #音声入力があるときの口描画 else: put_kuti = kuti2 #何もないときの口描画 return put_kuti def Select_Add(): #一番上に描画する画像(アクセサリーなど) put_up = kami #髪描画 return put_up #---------------- # 描画 #---------------- def ImageOut(screen, image_rect, bg, me, kuti, add): screen.fill((0, 255, 0, 0)) # 画面の背景色(緑) screen.blit(bg, image_rect) # ベース画像の描画 screen.blit(me, image_rect) # 目画像の描画 screen.blit(kuti, image_rect) # 口画像の描画 screen.blit(add, image_rect) # 上部画像の描画 return #---------------- # デバッグ用表示 #---------------- def DebugGraph(screen, Timer): print(Timer) return if __name__ == "__main__": main()
使い方
時間や音声の条件を元にばらばらだった画像が合成されるので、それで出力されたウィンドウをOBSに設定するだけ!
…ただ特筆したような機能はないし、作ろうと思えば上記情報をもとにすぐ作れると思うので、ちょっとしたネタにいかがですか!?
やろうと思えばキャラをもっと動かしたり音声の音量で表情パターン変えたりとかいろいろできそうですね。…あんまり凝りすぎてももうそれLive2Dで良くね?ってなりそうですが!