GyazoライクなGIFスクリーンキャスト共有ツール「Gifzo」をリリースしました

Gyazoのように画面のスクリーンキャストをGIFアニメで撮れるツール「Gifzo」をリリースしました。

Gifzo

Gifzoとは

Gifzo from Kazato Sugimoto on Vimeo.

Gifzoは宇宙一簡単にスクリーンキャストを共有できるサービスです。画面のキャプチャ動画をGIFアニメで超簡単に共有することができます。

画面領域を選択して録画すると自動的に動画がアップロードされて、撮った画像のページがブラウザに自動的に表示されます。Gyazoと似た操作感でとてもシンプルに使うことができます。

Gifzoでできること

Gifzoを使えば、画面上の"動き"をとても簡単に共有することができます。Webサイトの録画UIの動作の共有アニメのキャプチャなど様々な用途で使うことができます。

また、Gifzoではできるだけ画質を落とさないように画像を圧縮するため、綺麗で低容量なGIFアニメを作ることができます。自前で作るときのような細かい設定はまったく不要です。

また、作成したスクリーンキャストはMP4動画でも画像ページからダウンロードすることができます。

アップロードされたGIFアニメは例えば以下のようなURLで共有できます。

http://gifzo.net/7759673016a417db03ec0f67b478232a1943dc8d

現在のところ、Mac *1Windows *2で対応しています。こちらからクライアントをダウンロード(無料)できます。

こんなGIFアニメを作ることができます

これらは実際にGifzoを使って作られたGIFアニメーションです。

f:id:uiureo:20130521080009g:plain

f:id:uiureo:20130521081412g:plain

f:id:uiureo:20130521015719g:plain

f:id:uiureo:20130522201221g:plain

詳しい使い方

Macのクライアントの使い方を説明します。

Gifzoを起動すると、半透明のウィンドウがでてきてドラッグで録画する領域を選択することができます。(ESCキーでキャンセルしてアプリを終了することもできます)

選択が完了したらOption+Rキーで収録を開始します。
f:id:uiureo:20130521171058g:plain

Option+Rキーをもう一度押して収録を終了すると、自動的に動画がサーバーにアップロードされます。
f:id:uiureo:20130522000733g:plain

しばらく待つと、自動的にブラウザが開かれ、撮ったスクリーンキャストが表示されます。
f:id:uiureo:20130522001105g:plain

その他

Windowsクライアントは、@hidesysが作ってくれました。何も聴いてないのに僕が眠っている間に一晩で勝手に作ってて驚いた記憶があります。

あなたとGifzo, いますぐダウンロード

こちらのリンクからクライアントをダウンロード(無料)すればすぐに使えます。

Gifzo

よろしくお願いします!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

*1:OSX 10.7+

*2:Windows 2000+

GIFアニメ生成にImageMagickはオワコン、情強は高速なGraphicsMagickを使う

f:id:uiureo:20130519030836g:plain

大した話ではないけれど、GIFアニメをコマンドラインから作るならGraphicsMagickが便利なので共有します。

MP4の動画ファイルからGIFアニメを作ろうとすると、まずffmpegで動画を画像に分割してそれからimagemagickでGIFに結合するという方法があります。

% ffmpeg -i hoge.mp4 -r 2 %04d.png
% convert *.png hoge.gif

複数枚の画像をimagemagickでGIFに結合するのが実は結構時間がかかるため煩わしいことが多いです。場合によっては、数十秒かかったりする。

ImageMagickのfork版であるGraphicsMagickを使うと高速にGIFアニメを生成することができます。

GraphicsMagickのほうが3~4倍速い

GraphicsMagickを使えばImageMagickよりも3~4倍高速にGIF生成ができます。生成されるGIFの容量もGraphicsMagickのほうが若干小さい。

我々人類にとって貴重な遺産である愛生会病院のホームページを10秒程度撮った動画をGIFに変換して試してみました。動画から一秒2フレームずつ画像をpngで切り出したものをGIFに結合してベンチマークをとりました。

f:id:uiureo:20130519130719g:plain

png20枚(一枚500KB程度)をGIFに結合するのにImageMagick45.87秒かかったのに対し、GraphicsMagickは10.45秒しかかかりませんでした。生成されたGIFの容量もImageMagick4.5MBだったのに対し、GraphicsMagickは4.2MB300KBほど小さかった。

GIF生成にかかる時間はフレーム数にほぼ比例して長くなるため、大きなGIFファイルを作ろうとすると速度の違いはさらに顕著になります。

GIFアニメを作るときは大量のパターンを試すことが多いため、速いほうが製作効率が上がります。

コマンドもImageMagickとほとんど同じです。

% gm convert *.png hoge.gif

homebrewから簡単にインストールできる。

% brew install graphicsmagick

ときどきImageMagickにあるオプションがなかったりするものの、GIFアニメ用途ではGraphicsMagickが便利。

Express読んだ

Node.jsのWebアプリケーションフレームワークexpressのソースコードを読んだ。

Node.jsの書き方とかHTTPの仕様とか調べながらコード読んで勉強になった。

読むときに作ったメモを載せておく。テキトーすぎてまったく参考にならないと思う。

依存モジュール

気になったものだけをメモ

connect

ミドルウェアを使って拡張できるHTTPサーバーフレームワーク
便利なmiddlewareが色々入ってる

commander

コマンドパーサーみたいなやつ

range-parser

HTTPヘッダフィールドのrangeをパースするやつ
小さくて読みやすそう

fresh

http response freshnessを調べる単純なやつ
キャッシュ制御につかう

methods

ただのhttp method 一覧

send

static() file server
面白そう

connectを読む

expressはルーティング等の機能がconnectのmiddlewareとして実装されていて、connectに大きく依存する形で作られている。
そのため、expressを理解しようとなるとまずconnectのコードを読んで理解しないといけない。

senchalabs/connect · GitHub

使用例はこんな感じ

var connect = require('connect')
  , http = require('http');

var app = connect()
  .use(connect.favicon())
  .use(connect.logger('dev'))
  .use(connect.static('public'))
  .use(connect.directory('public'))
  .use(connect.cookieParser())
  .use(connect.session({ secret: 'my secret here' }))
  .use(function(req, res){
    res.end('Hello from Connect!\n');
  });

http.createServer(app).listen(3000);

lib/connect.js

ここからはじまる。connect()で呼び出されるのはcreateServer
同梱されてるmiddlewareをロードする

lib/patch.js

http.serverResponseにメソッドを追加する

lib/proto.js

app.useを定義したり
メインっぽい
抽象クラスみたいな感じ
lib/connect.jsから呼び出される

app.use

よく使うやつ
ミドルウェアをstackに積む
middlewareはこんな感じの何かするやつ。nextを呼び出すと次のやつにいく

function(req, res, next) {}
app.handle

リクエストを処理する
stackを下から順に見ていき、routeにマッチしたら実行していく
nextを繰り返す
おもしろい

next

次のミドルウェアに進む
次に処理するものなくなったり、処理が終わったらエラーを出したりとかする

app.listen

http.createServer(app)してlistenするだけ

http.createServer

http.Serverオブジェクトを返す
http.ServerはEventEmitterでリクエストが来るたびに'request'イベントを発火させる
function (request, response) { }
コールバックにはhttp.ServerRequestとhttp.ServerResponseが引数として渡される

createServerには[requestListener]を渡すことができて、自動で登録してくれる

expressを読む

lib/express.js

createApplicationがexposeされてる

connectのミドルウェアをexpress.*として見えるようにしたり

createApplication

connectの上にapplication(lib/application.js)を重ねてinitする

lib/application.js

中心的な処理

app.defaultConfigulation

initが呼び出す
middlewareを設定したり
app.routerを設定したりとか

app.use

connect#use()へのproxy

別のapplicationをmountすることとかもできる

app.engine

引数の拡張子に対して使用するtemplate engineを登録する

中でやってるのはとりあえずプロパティに代入するだけ

app.set

settingに代入するのと、参照するの
app.getの実体もこれ

app.enable

app.setでtrueを代入するだけ

app.disable

app.setでfalseを代入するだけ

app.configure

development, stage, productionなど環境に応じた設定

app.render

template engineで描画する

view.renderを呼び出してる

res.renderで呼び出されたり

lib/router/index.js

Routerがexposeされてる
router.middlewareにmiddlewareが入っていてapplication.jsではこれを使ってる

map

method(getとかpostとか)をキー、Routeオブジェクトの配列を値としたハッシュ

_dispatch

middlewareの実体

requestにマッチするrouteを取り出し
paramを適用したりする

面白かった

param

paramに設定されたcallbackを順番に実効する
たとえば /users/:id で

app.param('id', function(req,res,next,val) { 
  // hoge …..
})

だとこのコールバックに適切なパラメータを渡して実行する

paramのcallbackの実行が終わったら
routeのcallbackを順番に実行する

route

routeを定義する
app.getとかapp.postとかを扱うのはこれ
Routeオブジェクトを作ってRouter#mapに放りこむ

(this.map[method] = this.map[method] || []).push(route);
matchRequest

this.mapからrequestにマッチするrouteを探してきて返す

lib/middleware.js

X-Powered-Byをセットしたり
reqやresを初期化したりするmiddleware

lib/view.js

view.render(option, fn)

engineで描画する

lib/request.js

http.ServerRequestの拡張

lib/response.js

http.ServerResponse
地道な感じ

pure JavaScriptでアニメーションGIFを作る

こんばんは、国民的スポーツのアニメGIFについてのニュースをお届けします。
今回はクライアントサイドのJavaScriptだけでアニメーションGIFを作る方法を共有させて頂きます。

ふつうアニメGIFを作ろうと思うとimagemagickなどを使ってサーバーサイドで処理させると思いますが、今回紹介するのはブラウザだけでアニメGIFを作る方法です。

jsgif

antimatter15/jsgif · GitHub
jsgifというJavaScriptCanvasをアニメGIFに変換してくれる超絶便利ライブラリがあるのでこれを使います。
同名でアニメGIFをCanvasで制御再生できるライブラリがあって、そっちのほうが有名ですがそれとは別です。

どうやらAS3のライブラリをJSに移植したものみたいでソースコードを読もうとしても全然分からないけど、便利すぎるので全面の信頼をおいて使います。

だいたいこんな感じで使える。実際には画像をロードするのを待たないといけない。

var img1 = new Image(), img2 = new Image();
img1.src = 'sozai/1.jpg';
img2.src = 'sozai/2.jpg';

var encoder = new GIFEncoder();
encoder.setRepeat(0);
encoder.setDelay(100);
encoder.setSize(100,100);

context.drawImage(img1, 0, 0, canvas.width, canvas.height);
encoder.addFrame(context);

context.drawImage(img1, 0, 0, canvas.width, canvas.height);
encoder.addFrame(context);

encoder.finish();

気をつけること

クロスオリジン制約によるCanvasの汚染

canvasには外部ドメインから読み込んだ画像を描画したcanvasは"汚染"されて、画像として保存するなどデータを引き出すことができなくなるセキュリティ上の制約があります。
CORS Enabled Image | MDN

jsgifはcanvasを使って画像データを引き出しているので、外部ドメインから画像を読み込んでいる場合使うことができません。
外部ドメインの画像を使ってアニメGIFを作りたい場合は、CORSなプロキシを通すなどする必要があります。

file://で画像を参照する場合もクロスオリジン制約に引っかかるので、適当なHTTPサーバーを立てて動かす必要があります。

デモ

jsgifを使ったアニメGIF生成の簡単なデモを作ってみました。

GIF生成の処理は重いので、WebWorkerを使ってバックグラウンドで処理させるようにしています。

デモの様子はここから見れます。Chromeで動くと思います。素材にはパブリックドメインな人物画像を使用しています。
http://uiureo.github.com/jsgif-demo/

こんな感じの画像が生成されます。
f:id:uiureo:20121222000541g:plain

client.js
// Array{DOM Image} -> callback(dataURL)
function createGIF (args, callback) {
  var images = args.images || [];
  var option = {
    delay: args.delay || 100,
    repeat: args.repeat || 0,  // default: auto loop
    width: args.width || 400,
    height: args.height || 400
  };

  var canvas = $('#canvas')[0];
  var context = canvas.getContext('2d');

  canvas.width = option.width;
  canvas.height = option.height;

  // GIFは透明にできないから白色で塗る
  context.fillStyle = "rgb(255,255,255)";  
  context.fillRect(0, 0, canvas.width, canvas.height);

  var worker = new Worker('encoder.js');

  worker.postMessage({ cmd: 'start', data: option });

  images.forEach(function (image) {
    context.drawImage(image, 0, 0, canvas.width, canvas.height);

    // Workerにフレームのデータを送る
    worker.postMessage({ cmd: 'frame', data: context.getImageData(0, 0, canvas.width, canvas.height).data });

    context.fillRect(0, 0, canvas.width, canvas.height);
  });

  worker.postMessage({ cmd: 'finish' });

  worker.onmessage = function (e) {
    callback('data:image/gif;base64,' + encode64(e.data));
  };
}

// from https://github.com/antimatter15/jsgif/blob/master/Demos/b64.js
function encode64(input) {
	var output = "", i = 0, l = input.length,
	key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", 
	chr1, chr2, chr3, enc1, enc2, enc3, enc4;
	while (i < l) {
		chr1 = input.charCodeAt(i++);
		chr2 = input.charCodeAt(i++);
		chr3 = input.charCodeAt(i++);
		enc1 = chr1 >> 2;
		enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
		enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
		enc4 = chr3 & 63;
		if (isNaN(chr2)) enc3 = enc4 = 64;
		else if (isNaN(chr3)) enc4 = 64;
		output = output + key.charAt(enc1) + key.charAt(enc2) + key.charAt(enc3) + key.charAt(enc4);
	}
	return output;
}

$(function () {
  var srcs = ['sozai/1.jpg', 'sozai/2.jpg'];

  var images = srcs.map(function (src) {
    var image = new Image();
    image.src = src;
    return image;
  });

  // 画像が全ロードされるまで待つ
  window.onload = function() {
    createGIF({ images: images }, function (dataURL) {
      $("#image").attr('src', dataURL);
    });
  };
}());
encoder.js

WebWorkerでアニメGIFを生成する部分です。

importScripts('LZWEncoder.js', 'NeuQuant.js', 'GIFEncoder.js');

var encoder = new GIFEncoder();
onmessage = function (e) {
  if (e.data.cmd === "start") {
    var data = e.data.data;
    encoder.setRepeat(data.repeat);
    encoder.setDelay(data.delay);
    encoder.setSize(data.width, data.height);

    encoder.start();
  } else
  if (e.data.cmd === "finish") {
    encoder.finish();
    postMessage(encoder.stream().getData());
  } else 
  if (e.data.cmd === "frame"){
    encoder.addFrame(e.data.data, true);
  }
};

問題点

データが大きすぎてURLに収まらない
小さい画像ならなんとか収まってURLで参照できるけど、アニメGIF用途ではたいていURLに収まらない。URLをコピーして参照とかできない。ちょっと不便。
サイズがでかすぎたら名前をつけて保存ができなかったりする。つらいですね。

まとめ

pure JavaScriptでアニメGIFを作る方法をご紹介しました。
サーバーサイドを書くことなく、ブラウザだけでアニメGIFを作ることができるのでとても便利ですね。

以上、スポーツニュース速報でした。

Webカメラから超絶カッコいいプロフィール写真を撮れるWebサービス作った

Webカメラでめっちゃカッコいいプロフィール画像を簡単に撮れて便利.JS

インターネットの皆さん、こんばんは。国民的スポーツの一つであるアニメGIFに関する記事です。

今回、Webカメラから超絶クールなプロフィール画像を撮れるWebサービスを開発したのでご紹介させて頂きます。

SNSや履歴書などに貼るプロフィール写真を撮ったら思ったよりもカッコよくなくてつらい気分になったことはありませんか?
「動いてるときはもっとカッコよく見えてるはずなのに……」静止画になると急に生命力が失われた感じに見えてしまいます。とてもつらい思いになりますね。

そこで、簡単にもっとかっこいいプロフィール写真を撮りたいと思い、Webカメラから超絶クールなプロフィール画像を撮れるWebサービスを開発しました。
言い換えれば、Webカメラから撮った映像からアニメGIFを作れるWebサービスです。
サービス名は「Webカメラでめっちゃカッコいいプロフィール画像を簡単に撮れて便利.JS」です。よろしくお願いします。
Google Chromeで動きます。
Webカメラでめっちゃカッコいいプロフィール画像を簡単に撮れて便利.JS

使い方

Webカメラでめっちゃカッコいいプロフィール画像を簡単に撮れて便利.JS
f:id:uiureo:20121220021724p:plain

ページを開くと、Webカメラの許可を求められるので許可します。

撮る長さ、フレーム数、生成されるGIFのフレームの遅延時間などを指定できます。
「なめらか」「すばやい」などのボタンを押すとオススメ設定になります。

「撮る」ボタンを押すと撮影が開始されて、撮影が終了したらしばらく待つとアニメGIFが生成されます。

生成された画像は「名前をつけて保存」できます。
フレーム数が多いと時間がかかったり保存できなかったりするかもしれません。

たとえば、ワンクリックで下のようなダイナミックなプロフィール写真ができます。
f:id:uiureo:20121220022005g:plain

みかんが美味しい季節ですね。
f:id:uiureo:20121220024827g:plain

こんなポップでキュートな写真も撮ることができます。
f:id:uiureo:20121220025709g:plain

特徴

pure JavaScriptなのでブラウザ上だけで動作する

Webカメラからの映像の取得からアニメGIFの生成まですべてJavaScriptで行なっているのでブラウザ上だけで動作します。

WebRTCでWebカメラからの映像の取得を行っています。
アニメGIFの生成にはjsgifというライブラリを利用しています。
https://github.com/antimatter15/jsgif

どうぞお使いください

Webカメラでめっちゃカッコいいプロフィール画像を簡単に撮れて便利.JS

この記事は、拡散お願いしますアドベントカレンダー2012 19日目の記事です。拡散お願いします。
次は@_udonchanさんです。

Node.js+Expressでブラウザ上でアニメGIFを作るための便利ツール作った

日本人なら皆、日常的にアニメーションGIFを作って遊んでいると思う。野球、相撲、反原発デモに並ぶ国民的スポーツと言っても過言ではない。

スマートフォンアプリだとGifBoomという革命的便利ツールがあるからいいんだけど、PCで作ろうとなると良いツールがなくてimagemagickを直接叩くとかしなければならなくて困ってた。
アニメGIFを作るためのブラウザ上で動く何かがあればいいと思って作った。

名前は2012年に発売された革命的デバイスにちなんで"gifkobo"。

機能

https://dl.dropbox.com/u/23470717/gifkobo/screenshot.gif
主にできることとしてはこんな感じ。

  • コマンドから画像素材のあるディレクトリをコマンドから起動
  • アニメGIFに使いたい画像をクリックで選択するGifBoomっぽいUI
  • Delay(アニメを表示するときの遅延時間)とSize(生成するアニメの幅と高さ)の指定
  • 生成されるGIFのcanvas上での逐次プレビュー(生成されるGIFの大まかな様子が右の画面で分かる)
  • ドラッグ&ドロップで画像素材をアップロード

試しに動かすときに使えるようにid:catatsuyの画像素材が付録としてexample/にある。パブリックドメインなので、どうぞご自由にお使いください。

使い方

npmモジュールとして公開してる。素材にしたい画像のあるディレクトリを指定して起動する。

$ npm install gifkobo -g
$ gifkobo /path/to/your/images/

デフォルトでは3000番ポートにサーバーが起動する。
http://localhost:3000/にアクセスすると指定した素材画像を使ってアニメGIFが作れる。

技術的なこととか

使ったNode.jsのモジュールはこれくらい。express以外は一部で利用するくらいでそんなに使ってない。

今回は画面遷移のない小さいWebアプリケーションだったから、expressのようなシンプルなフレームワークを使うのはすごく楽だった。

感想

個人的に便利に使えてるし作って良かった。他の人にとっても便利かどうかはよく分からない。

割と適当に作ったから問題点は割とある。

  • Canvasでのプレビューの解像度がよくなくてぼやけた感じになる(canvasで伸縮してるから???)
  • Canvasでのプレビューと生成されるアニメGIFに結構差がある
  • UIあまり良くない
  • アニメGIFを素材として使おうとするとよく分からない挙動をする

色々あるけど、使ってるうちに困ったらその都度直していこうと思う。

Github

詳しくはGithubに書いてる。
uiureo/gifkobo · GitHub

色分けして表示するIRCログビューアをつくった

f:id:uiureo:20120619165510p:plain

uiureo/osirco · GitHub

IRCログの見るのであんまり気に入るのがなかったからRailsで作った。発言者の名前によって色分けをしたり、無限スクロールしたりする。データベースにログを放り投げるBotを適当に立てて使う。

色分けには前に作った文字列から色を生成するJS - 夢想ヒッチハイカを使った。

たぶん探せばこんなのいくらでもあると思うし、他の人が使えるようなものでもないから本当に個人用なんだけど自分では結構便利だと思って使ってる。