0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

wslでelixir その186

0
Posted at

概要

wsl(wsl2じゃない)で、elixirやってみた。
Livebookで、Live2D + Speech + lipsync 書いてみた。

写真

image.png

setup

Mix.install([
  {:kino, "~> 0.19"}
])

サンプルコード



defmodule KinoHTML.Live2d do
  use Kino.JS
  use Kino.JS.Live
  def new(toolbox) do
    Kino.JS.Live.new(__MODULE__, toolbox)
  end
  def speak(kino, text) do
    Kino.JS.Live.cast(kino, {:speak, text})
  end
  @impl true
  def init(toolbox, ctx) do
    {:ok, assign(ctx, toolbox: toolbox)}
  end
  @impl true
  def handle_connect(ctx) do
    {:ok, ctx.assigns.toolbox, ctx}
  end
  @impl true
  def handle_cast({:speak, text}, ctx) do
    broadcast_event(ctx, "speak", %{text: text})
    {:noreply, ctx}
  end
  asset "main.js" do
    """
export async function init(ctx, toolbox) {
  await ctx.importJS("https://cubism.live2d.com/sdk-web/cubismcore/live2dcubismcore.min.js")
  await ctx.importJS("https://cdn.jsdelivr.net/gh/dylanNew/live2d/webgl/Live2D/lib/live2d.min.js")
  await ctx.importJS("https://cdn.jsdelivr.net/npm/pixi.js@6.5.2/dist/browser/pixi.min.js")
  await ctx.importJS("https://cdn.jsdelivr.net/npm/pixi-live2d-display/dist/index.min.js")
  const canvas = document.createElement("canvas");
  canvas.style.height = "480px";
  canvas.style.width = "600px";
  ctx.root.appendChild(canvas);
  const cubism2Model = "https://cdn.jsdelivr.net/gh/guansss/pixi-live2d-display/test/assets/shizuku/shizuku.model.json";
  await new Promise(resolve => setTimeout(resolve, 50));
  const app = new PIXI.Application({
    view: canvas,
    autoStart: true,
    backgroundAlpha: 0
  });
  const model2 = await PIXI.live2d.Live2DModel.from(cubism2Model);
  app.stage.addChild(model2);
  model2.scale.set(0.3);

  let isSpeaking = false;
  let nextMouthValue = 0.0;
  let lastUpdateTime = 0;
  if (model2.internalModel && model2.internalModel.motionManager) 
  {
    const motionManager = model2.internalModel.motionManager;
    const originalUpdate = motionManager.update;
    motionManager.update = function (coreModel, deltaTime) {
      const result = originalUpdate.call(this, coreModel, deltaTime);
      if (isSpeaking) 
      {
        const now = Date.now();
        if (now - lastUpdateTime > 60) 
        {
          nextMouthValue = Math.random() * 0.5;
          lastUpdateTime = now;
        }
        coreModel.setParamFloat("PARAM_MOUTH_OPEN_Y", nextMouthValue);
      } 
      else 
      {
        coreModel.setParamFloat("PARAM_MOUTH_OPEN_Y", 0.1);
      }
      return result;
    };
  }
  
  ctx.handleEvent("speak", ({ text }) => {
    if (!text) return;
    const utterance = new SpeechSynthesisUtterance(text);
    utterance.onstart = () => {
      isSpeaking = true;
      lastUpdateTime = Date.now();
    };
    const stopLipSync = () => {
      isSpeaking = false;
    };
    utterance.onend = stopLipSync;
    utterance.onerror = stopLipSync;
    window.speechSynthesis.cancel();
    window.speechSynthesis.speak(utterance);
  });
}
    """
  end
end




kino = KinoHTML.Live2d.new(0)
   
KinoHTML.Live2d.speak(kino, "画面が表示されましたか?今度はうまくいくはずです。")

以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?