‘プログラム’ カテゴリーのアーカイブ

HTML内でIDな要素はグローバルに参照できる!

 プログラム
 公開日:2015年5月3日

 先日、とあるJavaScriptなソースを眺めていた所、
変数宣言もなくHTML内のIDな要素を参照しているのを発見しました。
HTMLを見てみると確かに同じ名前のIDな要素が見つかりましたが、
var hoge = document.getElementById('hoge'); とかやって
参照するものだとばかり思っていたので、
なんじゃこれはと気になった次第です。

 調べてみた所、
HTML内でIDをつけた要素はJavaScriptのグローバル変数に格納される
という記事を見つけました。
いやぁ~、いまの今まで全然知りませんでした。
HTML5の仕様の一つになっているようです。

 ただ、ブラウザによって実装は異なるようです。
先の記事を引用すると、

Chromeはwindowのプロトタイプで、
Firefoxはwindowのプロトタイプのプロトタイプで、
ie11(とie9)はwindowそのもののプロパティに出てきますね。

となっており、同じグローバルでも違いがあるようです。

 さらに興味深いことに、
グローバル参照と getElementById() とで速度を比較した方がいました。
こちらによると getElementById() の方が速いという結果になりました。
jsPerfで試せるようになっていたので、
実際にやってみたら確かにそのようになりました。
私の環境では5倍くらいの差が出ていました。

 結論としては、

特定の要素にname属性をつけた場合も同じようにアクセスできたり、
windowオブジェクトがもともと持ってるプロパティ名は上書きできないとか色々ありました。

とあるように、環境によって副作用がありそうなのと、
速度的にもメリットがなさそうなので、
素直に getElementById() を使うのが良い
ということになりそうですね。
今までのやり方を変えなくていいんです(^_^;)

 

ブラウザで録音してMP3化(2)

 プログラム
 公開日:2015年4月29日 / 更新日:2016年3月10日

★2016年3月10日追記。
いつのまにかChromeで動作しなくなっていることに気づきました。
いつ頃からなのかは不明です。
調べてみたところ最近のChromeでは、
HTTPSなセキュアな環境でないと該APIが許可されないようです。
なんでやねん!
ローカルにサーバー立ててやってみるとHTTPでも行けるのですが・・・。
Firefoxで試してみると一応動くのですが、
何故か数秒経つと音が聞こなくなってしまう・・・。
私のPCの環境だけの現象?

 先日、ブラウザで録音してMP3化というのをやりましたが、
CBRだけでなくABRやVBRにも対応しました。
あわせてビットレート等も調整できるようにしてみました。

 なお、libmp3lame.js はこちらではなく、
forkされたこちらの版に変更しました。
前者はBUFSIZEが固定なため、こちらの例にあるように
入力サイズに応じて逐次的に複数回処理する必要がありました。
後者はBUFSIZEを入力サイズに応じて自動調整してくれるので、
1回のパスでも完了可能になっています。
Recordmp3js が1パスでやってるので不思議に思っていたのですが、
どうやら後者の版を使っていたようですね。
ただ、今回はプログレス表示をする関係で、
複数回のパスで処理するようにしているので、
どちらの版でも基本的には問題ないはずです。

 ということで、デモを試すにはこちらからどうぞ。

 ところで、Web API には MediaRecorder というのがあるようで、
こちらの例にあるようなコードを書けば、
ブラウザの Native な機能だけで ogg(opus) にエンコードできるようです。
ただし現状で MediaRecorder に対応しているのは
Firefox だけのようです・・・(^_^;)

ブラウザで録音してMP3化

 プログラム
 公開日:2015年4月22日 / 更新日:2016年3月10日

★2016年3月10日追記。
いつのまにかChromeで動作しなくなっていることに気づきました。
いつ頃からなのかは不明です。
調べてみたところ最近のChromeでは、
HTTPSなセキュアな環境でないと該APIが許可されないようです。
なんでやねん!
ローカルにサーバー立ててやってみるとHTTPでも行けるのですが・・・。
Firefoxで試してみると一応動くのですが、
何故か数秒経つと音が聞こなくなってしまう・・・。
私のPCの環境だけの現象?

★2015年4月30日追記。
CBRだけでなくABRやVBRにも対応してみました。
詳しくはこちら

 Webな audio API について調べていたら、
ブラウザだけでマイク録音」というのを見つけました。
試しにやってみたら確かにできますね。
ブラウザだけで出来るのが面白いので中身をちょっと見てみました。

 Recordmp3js はいったんWAVで取得した後にMP3に変換してたので、
Recorder.js を改造して直接MP3に変換できるようにしてみました。
ついでにプログレス表示できるようにもしてみました。
こちらこちらを参考に改造しました。

 作ってみたデモはこちらから試せます。
CBR 128Kbps で出力します。
エンコーディングするのにそれなりな時間を要する感じなので、
録音時間は最大で60秒に制限してあります。
なお、MP3に変換するのに libmp3lame.js を使いました。


 

zip.jsを触ってみた

 プログラム
 公開日:2015年4月9日

 ふと、JavaScriptでZIPファイルを扱うのに
良さげなライブラリはないかなと探してみたら、
JSZipzip.js というのを見つけました。

 JSZip は node.js にも対応しているようです。
デモ(,,)の出来が良さげだったので、
zip.js を触ってみることにしました。

 使い方は、上述したデモのソースを参照したら大体理解できました。
ダウンロードしたファイルにサンプルソースも付いてるので、
これを参照するのも良さそうです。

 デフォルトで web worker に対応しているので、
圧縮や展開を別スレッドで実行して性能向上が期待できそう。
web worker として読み込まれるスクリプトファイル、つまり
z-worker.js, deflate.js, inflate.js の3つの置き場所は
以下のように必要に応じて調整できるようになっています。

 ただ、日本語のファイル名は文字化けしてしまうので改造してみました。
文字コードを変換するために、encoding.js を使います。
zip.js より前にscriptタグを使って読み込むようにします。
ZIP内部のファイル名エンコーディングは、
ASCII か UTF8 のいずれかになるようです。
SJIS等のマルチバイトはASCIIとして処理されるので文字化けするみたい。
zip.js の一部を以下のように改造して対応しました。

 ところで、
zip.js には ZIPファイルを FileSystem のように扱える
zip-fs.js というのが同梱されています。
zip-fs.js では zip.js の FileWriter という機能を使っているのですが、
なぜか zip.fs にはその機能が実装されていません。
デモ3においてフォルダの内容をZIPとしてexportするとエラーとなります。
なぜ実装されていないのかは不明。
FileSystem API を使ってどうにかするしかないのか?
zip-fs.js を使わなくても圧縮や展開はできるのでとりあえず問題はなさそう。

Emscriptenをやってみた

 プログラム
 公開日:2014年12月16日 / 更新日:2014年12月18日

★2014年12月18日追記。
「JPEGの半分サイズ」は正確でないようです。
こちらで検証されてます。

先日、
JPEGの半分サイズで同品質という新しい画像形式「BPG」
という記事に興味を持ちました。
HTMLのimgタグで拡張子bpgが扱えるようになってたので、
どうやってるんだろと思って
ちょっと中身を見てみたところ、
document.imagesを走査して、拡張子がbpgだったら
Canvasオブジェクトを作って、JavaScriptで描画するようになってました。
で、そのJavaScriptはEmscriptenで変換されたものでした。

Emscriptenというのは、ざっくり言うと
C/C++ —> LLVM —> JavaScript
という感じに変換するコンパイラな感じ。
C/C++で書かれたものがJavaScriptに変換されて
Webで利用できてしまうというのがナイスです。

ちなみに、
当ブログの「three.jsで遊んでみる」では
物理エンジンとしてammo.jsというのを利用していますが、
これはBulletというC++で書かれたのが変換されたものだったりします。

そんなわけでEmscriptenって何かスゲーとあらためて感じたので、
実際にちょっと試してみた次第です。
clangとかNode.jsとか必要になるらしいので、
unix系な環境でないと動かないのかなと思ってたら、
Windows向けのSDKとかあるのでこれを使えばよさそうです。

というわけで、こちらからSDKをダウンロードします。
「Emscripten SDK Web Installer」というのを選べばOKだと思います。
あとは普通にインストールするだけ。
clangとかNode.jsとか入れてくれます。

初回インストール時には必要ないと思いますが、
最新版に更新する際は、インストールしたフォルダにおいて
コマンドラインから以下のように入力すればよいようです。
> emsdk update
> emsdk install latest
> emsdk activate latest

Tutorialにしたがって、定番の hello_world.cを変換してみます。
ちなみに中身は以下の通り。

emscriptenのフォルダに移動して、
コマンドラインから以下のように入力します。
> emcc tests/hello_world.c
そうすると、 a.out.jsというファイルが出来るので、
> node a.out.js
と入力して実行すると「hello,world!」と表示されます。

数行のコードがどのようにJavaScriptに変換されているんだろうと思って、
a.out.js の中身を見てみると・・・なんかスゴイことになってます。
行数が約1万、ファイルサイズが357KBくらいあります・・・(^_^;)
大部分は実行するのに必要なお膳立てな部分なようで、
本体は _main となっている所のようです。

なるほど、それっぽく変換されてるけど、
機械的に変換されるので
人間にとっての可読性は期待しない方が良さそうです(^_^;)

ちなみに「公開時に推奨」となっている
最適化オプション -O2 を付けて変換すると、
> emcc -O2 tests/hello_world.c
ファイルサイズが149KBくらいまで小さくなります。
人間にとってはさらに可読困難になりますが(^_^;)