WebAssembly をウェブブラウザーで活用する(1)

この記事は ゆるWeb勉強会@札幌 Advent Calendar 2020 の 12日目です 😀

今年 2020年、WebAssembly は W3C 勧告に到達し、モダンウェブブラウザーで安心して WebAssembly を活用できるようになった年となりました。

また、ウェブブラウザー外で WebAssembly を動作させ、さまざまな環境で動作するユニバーサルバイナリーとして、コンテナー技術やマイコンなどで動作させる動きも広がった年でもありました。

この記事では、まずはウェブブラウザー視点から、WebAssembly が現在どのように活用され初めているのかを紹介してみたいと思います。

WebAssembly でできること、できないこと

WebAssembly の実態は低レベルマシンコードで、ウェブブラウザーなどに実装される WebAssembly のランタイムがこれを読み込み、プログラムとして実行する環境です。

現在、さまざまなコンピューター言語が WebAssembly に対応しており、それらの言語でかかれたプログラムを WebAssembly にコンパイルし、ウェブブラウザーで実行することができます。

ウェブブラウザーではこれまで、プログラム言語としては JavaScript しか動作しませんでしたが、WebAssembly の登場により、JavaScript 以外の言語のプログラムも実行することができるようになりました。

WebAssembly に「ネイティブ」対応している言語は多くありますが、自分が把握している言語は次のとおりです。

  • C/C++
  • Rust
  • AssemblyScript
  • Go
  • Swift

「ネイティブ」と書いたのには訳があり、WebAssembly 上で動作する言語はその他にも多数存在し、たとえば Python なども動作しますが、スクリプト言語のインタープリタや JIT は、元をただせば C/C++ でつくられており、WebAssembly が C/C++ に対応していることに立脚すると、それらのインタープリタ自体を WebAssembly で動作させてしまえば、ウェブブラウザーで Python が動作する、、そういう仕組みになっています。(C#/WebAssembly などはこの方式です)

さて、このように WebAssembly では多数の言語が動作しますが、その言語でつくられたソフトウェアはそのままでは動作するというわけではありません。ウェブブラウザーで動作する WebAssembly は現在のところ、DOM などのウェブブラウザーの機能(Web IDL)にアクセスすることができないからです。

つまりユーザーへの入出力部分(画面を描くであるとか、クリックを受け付けるとか)は、従来の JavaScript で作成し、処理の部分のみを WebAssembly に投げるようにプログラムを構成します。これが現在のウェブブラウザー上の WebAssembly でできない部分です。

ちなみに、今年 W3C 勧告となった WebAssembly の仕様は MVP(最初)の仕様群となっています。

ウェブブラウザーを含む各 WebAssembly ランタイムは次の仕様となる Proposals を絶賛先行実装中で、これらの実装が進むと WebAssembly から直接ウェブブラウザーの機能(Web IDL) へのアクセスも可能になります。(そのようになるように作業が進められています)

実際に使えるようになるのは、来年か再来年かになるかと思いますが、、楽しみです!

WebAssembly 活用例

WebAssembly のできることできないことが分かったところで、WebAssembly の活用例をみながら、どうやって実装しているのかを紹介していきたいと思います。

Ruffle A Flash Player emulator written in Rust

まずは、ニュースなどでもでていましたので知っている方もいらっしゃるかもですが、Adobe Flash を WebAssembly で実装した Ruffle。

https://github.com/ruffle-rs/ruffle

A Flash Player emulator written in Rust

ウェブブラウザーのプラグインで Flash サポート終了するなら、WebAssembly でつくってしまえば良いのでは?という発想よりつくられた、そのまま .swf ファイルが実行できるプログラムで Rust 製です。

デモが次のサイトから見ることができます。お手持ちの .swf があれば動かしてみると面白いかもしれません。

https://ruffle.rs/demo/

描画は canvas を、音声は WebAudio を JavaScript でインターフェースし、.swf の解析や実行を Rust 側で行っています。

同様に Microsoft Silverlight も WebAssembly に移植した実装が存在します。

https://opensilver.net/

ffmpeg.wasm

ウェブブラウザーが、どのような画像形式や動画再生をサポートするのかでやきもきする時代は WebAssembly の登場により終焉を迎えました。なぜならば、それらのデコーダーは C/C++ でかかれているからです。つまりそのプログラムをそのまま WebAssembly にしてしまえば、どのような画像でも動画でも再生できてしまいます。

というわけで、ffmpeg は様々な動画コーデックをもつ有名な C/C++ でかかれたオープンソースですが、これを WebAssembly コンパイルにしてインターフェースしたのが ffmpeg.wasm になります。動画再生だけはなく生成やエンコードも可能です。

https://github.com/ffmpegwasm/ffmpeg.wasm

FFmpeg for browser and node, powered by WebAssembly

ffmpeg.wasm は npm パッケージ化されていますので、使いたいなぁと思ったら、package.json の依存に加えるだけで使うことができます。

このような感じで WebAssembly できていると知らずに node のパッケージを使っていることも増えているのではないかと思います。(自分が確認したものでは .gz を展開するライブラリーが .wasm を使っているパターンがありました。

poton Rust/WebAssembly image processing library

動画に続いて画像処理系のライブラリーです。

これまでも画像に対してフィルターをかけたいなどといった場合は、CSS でネイティブに備わる機能が使えましたが、自分の思ったとおりの処理をしたい場合は、JavaScript で行う必要がありました。

もちろん JavaScript でもプログラミング可能ですが、画像処理に関してはプログラムの書きやすさを考慮すると他の言語を使ったほうが有利です。また WebAssembly にすることで高速化がかなり期待できます。

poton は Rust で実装された画像処理ライブラリーで、減色やリサイズ、フィルター、回転などなどの処理を WebAssemby で行うことができます。

デモが次のサイトから確認できます。

https://silvia-odwyer.github.io/photon/demo.html

こちらのライブラリーも npm 化されていますので、手軽に自分のプログラムから利用可能です。


ウェブブラウザーで動作する WebAssembly は、高速性もさることながら、さまざまな言語のエコシステムをそのまま活用できるのが大きな魅力の一つです。

WebAssembly 登場以前は、行いたいと思った処理を JavaScript で書き直す必要がありましたが、今後はその必要がなくなり、特に C/C++/Rust でかかれたすぐれたライブラリーをそのまま使うことができます。

次の回では、C/C++ もしくは Rust でかかれたプログラムを WebAssembly に移植して動作させるデモをやってみたいと思います!(続く

関連

コメントを残す

メールアドレスが公開されることはありません。