LoginSignup
4
3

More than 5 years have passed since last update.

Canvasから動画を生成するWebサービスを試作してみた。

Posted at

はじめに

3年ぶりの投稿です。
最近、Codepenなどを使ってCanvasで遊んでいるのですが、Canvasの画像・動きを動画として残せないかと考えるようになりました。
調べてみると、CCapture.jsなど、Canvasから動画を生成するライブラリがあるようなので、Herokuを使って、簡単なCanvas動画生成サービスを作ってみました。

作ったもの

成果物   :CapCanvas
ソースコード:Github

使い方

htmlヘッダーに以下の行を追加します。なお、idはcanvasのid、fpsはフレームレート、timeは録画時間(ms)を指定します。
'C'キーを推すとCanvasのキャプチャが開始され、録画終了後、動画(webm)がダウンロードされます。
<script type="text/javascript" src="https://capcanvas.herokuapp.com/capcanvas/id=app&fps=60&time=10000"></script>

実装

■JavaScript
Jsは、CCaputureのサンプルコードを参考に、以下のように実装しました。なお、$URL$ID$FPS$TIMEはサーバー側で文字列に置換します。

CapCanvas.js
window.onload = function(){
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "$URL";
document.body.appendChild(script);
};
window.addEventListener('keydown', event => {
if(event.key=='c'||event.key=='C'){
let canvas=document.getElementById("$ID");
startCapture(canvas,$FPS,$TIME);
}
});
let startCapture=function(canvas,fps,time){
let cap=new CCapture({format:'webm',framerate: fps,verbose: true});
let render=function(){
requestAnimationFrame(render);
cap.capture( canvas );
};
requestAnimationFrame(render);
cap.start();
setTimeout(function(){
cap.stop();
cap.save();
},time);
};

■サーバー
サーバー側はリクエストパラメータを解析し、CapCanvas.jsを書き換えて送信します。
個人的にお気に入りのSpark Frameworkで作成しています。

Main.java
package net.termat.webapp.capcanvas;

import static spark.Spark.get;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import spark.ModelAndView;
import spark.Spark;
import spark.template.mustache.MustacheTemplateEngine;

public class Main {
    private static String code;

    public static void main(String[] args) {
        Spark.staticFileLocation("/public");
        code=getJs();
        Optional<String> optionalPort = Optional.ofNullable(System.getenv("PORT"));
        optionalPort.ifPresent(p -> {
            int port = Integer.parseInt(p);
            Spark.port(port);
        });

        get("/", (request, response) -> {
            Map<String, Object> model = new HashMap<>();
             return new ModelAndView(model, "index.mustache");
        }, new MustacheTemplateEngine());

        get("/capcanvas/:param", (request, response) -> {
            try{
                String url="https://capcanvas.herokuapp.com/js/CCapture.all.min.js";
                Map<String,String> map=paramMap(request.params("param"));
                String id=map.get("id");
                String fps=map.get("fps");
                String time=map.get("time");
                response.status(200);
                String ret=new String(code);
                ret=ret.replace("$URL", url);
                ret=ret.replace("$ID", id);
                ret=ret.replace("$FPS", fps);
                ret=ret.replace("$TIME", time);
                return ret;
            }catch(Exception e){
                e.printStackTrace();
                response.status(400);
                response.type("application/json");
                return "";
            }
        });

    }

    private static String getJs(){
        try{
            URL url=Main.class.getResource("CapCanvas.js");
            BufferedReader br=new BufferedReader(new InputStreamReader(url.openStream()));
            StringBuffer buf=new StringBuffer();
            String line=null;
            while((line=br.readLine())!=null){
                buf.append(line);
            }
            return buf.toString();
        }catch(Exception e){
            return "";
        }
    }

    private static Map<String,String> paramMap(String param) throws Exception{
        Map<String,String> ret=new HashMap<String,String>();
        String[] p=param.split("&");
        for(int i=0;i<p.length;i++){
            String[] k=p[i].split("=");
            if(k.length<2)continue;
            ret.put(k[0], k[1]);
        }
        return ret;
    }
}

デプロイ

herokuへは、heroku-maven-pluginを使用してデプロイしました。
Port番号の解決に気が付かず、実際に動作させるまで2~3時間かかってしまいました。

4
3
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
4
3