画像をサーバーに送らないWebツールの仕組み

Web のサービスで写真を加工するとき、多くの場合、写真はいったんサービスのサーバーに送られ、サーバーで処理された結果が戻ってきます。33msec の Web Mask Studio(写真の顔や文字を隠すツール)と Video Inspector Pro(動画のコマ送り・比較ツール)は、写真や動画をサーバーに送りません。ページを開いたブラウザの中だけで処理しています。

この記事では、その仕組みと、なぜそう作ったのか、この作り方の弱点を説明します。

なぜサーバーに送らないのか

Web Mask Studio は、写真に写った顔や住所、位置情報を隠すためのツールです。人に見られたくないものを隠すための道具なのに、隠す前の写真を知らないサーバーに送ってしまうのでは、順番が逆になってしまいます。サーバーに送らなければ、運営者である私も写真を見ることができません。「預からない」ことが、いちばん分かりやすい安全の約束だと考えました。

動画のツールも同じです。仕事で扱う映像や、子どもの運動会の動画など、外に出したくない動画は少なくありません。動画はファイルが大きいので、サーバーに送らないほうが、待ち時間も短くなります。

ファイルを読み込む仕組み

Web ページは、利用者が選んだファイルを、ブラウザの中で読み込むことができます。ファイルを選ぶボタンや、ドラッグ&ドロップで渡されたファイルは、ページの JavaScript から読めますが、ページがそのファイルをどこかへ送る処理を書かない限り、外には出ていきません。

33msec のツールは、読み込んだ写真や動画を外部へ送る処理を持っていません。アクセス解析(Google アナリティクス)には、「画像を読み込んだ」「保存した」「顔を探した」といった操作の回数だけを送り、ファイル名や写真の撮影情報(EXIF)、画像・動画の中身は送りません。

写真を隠す処理

写真の黒塗り・モザイク・ぼかしは、ブラウザの Canvas(画面に絵を描くための仕組み)で行っています。写真を Canvas に描き、隠したい範囲の画素を塗りつぶしたり、ブロックごとの平均の色に置き換えたりします。モザイクの粗さによって文字がどこまで読めるかは、「モザイクの粗さで、文字はどこまで読めてしまうか」で試しています。

加工した写真は、Canvas から新しい画像ファイルとして保存します。Canvas から作った画像には元の撮影情報が入らないので、加工して保存した写真からは、位置情報などの EXIF がなくなります。

位置情報だけを消す処理

複数の写真の位置情報をまとめて消す「一括モード」では、写真を描き直さずに、ファイルの中の撮影情報の部分だけを取り除いています。

  • JPEG: ファイルは「マーカー」と呼ばれる区切りで分かれた部品の集まりです。撮影情報(Exif・XMP など)の部品を取り除き、色の再現に必要な部品と画像のデータはそのまま残します。そのため、画質は変わりません。
  • 写真の向き: スマートフォンの写真は、向きの情報で縦・横を表していることがあります。向きの情報を消すと写真が横倒しで表示されるため、向きだけを持つ最小の情報を入れ直しています。
  • PNG: 画像の表示に必要な部品と色の情報だけを残し、撮影情報や文字の情報の部品を取り除きます。

顔の自動検出

顔を自動で見つける処理には、機械学習のモデル(顔を見つけるように学習済みの計算の手順)を使っています。使っているのは、画像処理のライブラリ OpenCV のモデル集で公開されている顔検出のモデル YuNet です。これを、ブラウザの中で機械学習のモデルを動かすためのライブラリ ONNX Runtime Web で動かしています。計算には WebAssembly(ブラウザの中で速く計算するための仕組み)を使います。

モデルのファイル(約 14MB)は、「顔を探す」を初めて押したときに mask.33msec.com から読み込みます。これは端末が「受け取る」通信で、写真は送りません。

モデルに入力できる画像は 640×640 ピクセルです。大きな写真では小さく写った顔を見落としやすいので、写真全体を縮めて 1 回探すのに加えて、写真を 640 ピクセルのタイルに分けて、タイルごとにも探しています。

動画の処理

動画のコマ送りでは、動画ファイルの中にある各フレームの表示時刻を読み取って「時刻表」を作り、指定したフレームを正確に表示します。スマートフォンの動画のように、フレームの間隔が一定でない(可変フレームレートの)動画でも、実際の表示時刻でコマ送りできます。

ファイルの中身の読み取りと書き出しには、ブラウザの中で動く動画のライブラリ Mediabunny を、映像の復元(デコード)にはブラウザの機能 WebCodecs を使っています。区間の切り出しや、2 つの動画を並べた比較動画の書き出しも、ブラウザの中で行います。

本当に送っていないことを確かめる方法

いちばん簡単なのは、通信できない状態で使ってみることです。Web Mask Studio は、一度開くとツールのプログラムを端末に保存する(Service Worker という仕組み)ので、そのあと機内モードにしても、写真を読み込んで、隠して、保存できます。通信できない状態で最後まで使えれば、加工と保存に通信を使っていないことが確かめられます。

パソコンのブラウザなら、開発者ツールの「ネットワーク」の欄で、ページが行った通信をすべて見られます。写真を読み込んで保存するまでの間に、写真の大きさに見合うような送信がないことを確かめられます。くわしい手順は「画像が送信されていないことを確かめる方法」にまとめています。

この作り方の弱点

ブラウザの中だけで処理する方法には、弱点もあります。

  • 端末の性能に左右される: 大きな写真の顔検出や、長い動画の書き出しは、古いスマートフォンでは時間がかかります。
  • メモリの上限がある: iPhone や iPad のブラウザは、Canvas で扱える画素の数に上限(約 1,677 万画素)があります。Web Mask Studio では、それより大きな写真は縮小してから編集するため、保存した写真の画素数が元より少なくなります。
  • ブラウザによって使える機能が違う: WebCodecs に対応していないブラウザでは、動画の一部の機能が使えません。

開発でいちばん苦労したのは、こうした端末やブラウザの違いでした。パソコンでは問題なく動いても、スマートフォンでは大きな写真で処理が止まったり、ブラウザによって動画の同じ時刻に別のコマが表示されたりします。たとえば、コマ送りでフレームの境目ちょうどの時刻を指定すると、ブラウザによっては前のコマや次のコマが表示されることがあったため、フレームの開始から少し後ろの時刻を指定するようにしています。

サーバーで処理すれば、こうした違いを気にせずに済みます。それでも、写真や動画を預からないという約束を守るために、これからもブラウザの中だけで処理する作り方を続けていくつもりです。

出典

関連するツール

ほかの記事

  • 全国1,000以上の路線ページをどう作ったか

    Rail Density Explorer の線区・事業者ページ(合わせて1,000ページ以上)を、国土交通省の鉄道統計年報と JR 各社の公表資料からどう作ったか、データ集めでつまずいた点とあわせて説明します。

    ・サイトの作り方
  • 輸送密度が高い路線トップ20

    全国の鉄道の線区・区間を2023年度の輸送密度(1日あたりの平均の乗客数)が高い順に並べ、上位20の顔ぶれを調べました。山手線は1日約94万人で、最も少ない区間の約4万7千倍でした。

    ・鉄道のデータ
  • JR北海道の線区別の収支(宗谷線・石北線・根室線などの営業係数)

    JR北海道が公表している2023年度の線区別の収支から、宗谷線・石北線・根室線・釧網線などの営業収益・営業費用・営業係数を比べ、輸送密度との関係を調べました。

    ・鉄道のデータ