本記事は生成AIと共同で執筆しています。事実関係は可能な範囲で公式ドキュメント等と照合していますが、誤りが含まれている可能性があります。重要な判断を行う前にご自身でも一次情報をご確認ください。

はじめに(とおことわり)

ROIS-DS 人文学オープンデータ共同利用センター(以下 CODH)のホームページ codh.rois.ac.jp が長期メンテナンスのためサービスを一時停止しています(ROIS-DS による 2026 年 2 月 24 日付公式アナウンス、再開時期未定)。

デジタル源氏物語 では、「パタパタ顔比較」 と呼んでいる挿絵の顔比較機能で CODH の vdiff.js(2 枚の画像を重ね合わせて差分を可視化するツール)を直接呼び出していたため、CODH 停止以降この機能が利用できない状態になっていました。CODH のサービス再開までのつなぎとして、Wayback Machine から vdiff.js の配布物を取り出して自サイト側に暫定ミラーを置く対応を取ったので、その手順をまとめます。

本記事の内容は CODH のサービス再開までの暫定対応です。

  • vdiff.js は MIT ライセンス(CODH/core contributor: Jun HOMMA(@2SC1815J)氏)で公開されており、再配布自体は許諾されています(帰属表示は維持)
  • ただし、Wayback の特定時点スナップショットで凍結してしまうと、その後のバグ修正や機能改善を取り込めません
  • サービス再開後は速やかに各 URL を本家に戻し、ミラーは順次撤去する前提です

CODH には vdiff.js 以外にも IIIF Curation Viewer / Manager / Editor / Player / Board や そあん(soan)などのブラウザベースのツール群があります。本記事の手順は他ツールにも共通で適用できますが、ツール固有の落とし穴(依存ファイル数の多さ、<script> タグから見えない実行時依存など)は別記事 CODH ツール群の暫定ミラー専用リポジトリを GitHub Pages で立てる にまとめてあります。

また、サイト側のフレームワーク(Nuxt 等)特有のハマりどころ — 静的ジェネレータの crawler が static/<ツール名>/index.html を 404 アプリシェルで上書きしてしまう問題や、旧 Service Worker のキャッシュで反映が遅れる問題 — は別記事 Nuxt 2 generate で static/ 配下の埋め込みアプリが 404 ページに上書きされる問題と、旧 Service Worker の退役 にまとめています。

前提となる症状

デジタル源氏物語の場合、https://genji.dl.itc.u-tokyo.ac.jp/picture/face/(パタパタ顔比較)から画像比較を起動するリンクが、

<a href="http://codh.rois.ac.jp/software/vdiffjs/demo/?img1=...&img2=...">

の形で CODH の vdiff.js デモアプリを直接呼び出していました。CODH ホストへ到達できなくなった結果、機能全体が利用不能になっていました。

全体方針

  1. Wayback Machine の id_ フラグで生バイトを取得し、wombat 注入を避ける
  2. ZIP 配布物(vdiffjs_latest.zip)は Wayback にアーカイブされていなかったので、demo/index.html と参照されている JS / CSS / 画像等を個別にミラー
  3. 自サイトの公開ディレクトリ配下に vdiff/ として配置し、/vdiff/?... で配信
  4. 既存の <a href="http://codh.rois.ac.jp/software/vdiffjs/demo/?..."><a href="/vdiff/?..."> に置換

1. Wayback Machine から「生」のアセットを取る

Wayback Machine は CSS/JS も保存しています。ただし通常の閲覧 URL(/web/<timestamp>/<orig_url>)では、JavaScript の先頭に wombat という URL リライト用シムが注入されてしまい、リライト対象外の環境(自サイトに置き直した状態)では動作しないことがあります。実際 vdiff.js のラッパー JS でこれに引っかかり、UI は表示されてもサムネイル / 比較プレビューが出ない症状が再現しました。

これを避けるためには、URL に id_ フラグ(identity / 生バイト)を追加し、加えて --compressedContent-Encoding: gzip を自動展開させます(id_ は原本キャプチャ時の Content-Encoding をそのまま返すため、原本が gzip だった場合は curl 側で展開する必要があります)。

TS=20250822143200
URL=https://web.archive.org/web/${TS}id_/http://codh.rois.ac.jp/software/vdiffjs/demo/vdiffjs/vdiff.bundle.min.js

# wombat 注入なしの生 JS が手に入る
curl -sL --compressed --max-time 60 "$URL" -o vdiff.bundle.min.js

Wayback の URL フラグ:

フラグ用途
(なし)通常閲覧。HTML はバナー、JS は wombat 注入あり
if_iframe 用ヒント。実装上は mp_ 相当として扱われ、HTML にバナーは挿入され、JS にも wombat 注入が残ることが多い
id_identity。リライトを一切行わず、原本バイトをそのまま返す(HTML/JS/CSS とも素のまま)

JavaScript / CSS / 画像 / フォントなどの配布物としての復元には id_ が正しい選択です。

スナップショットの時点を選ぶには CDX API も便利です:

curl -sL "http://web.archive.org/cdx/search/cdx?url=codh.rois.ac.jp/software/vdiffjs/demo/vdiffjs/vdiff.bundle.min.js&output=json&limit=20"

2. デモアプリ一式の構成を解析する

vdiff.js のデモアプリ https://codh.rois.ac.jp/software/vdiffjs/demo/index.html が参照している外部リソースを、アーカイブから取り出して列挙します。

# まず HTML を取得
curl -sL --compressed "https://web.archive.org/web/2025id_/http://codh.rois.ac.jp/software/vdiffjs/demo/" -o demo.html

# 参照アセットを列挙(外部 CDN, GA, Wayback 自身は除外)
grep -oE '(href|src)="[^"]*"' demo.html \
  | grep -ivE "googletagmanager|google-analytics|web-static|web.archive|fonts.googleapis|favicon"

vdiff.js 本体の最小構成は以下の 6 ファイルでした(HTML 1 + JS/CSS 4 + OpenCV)。

demo/
├── index.html
├── vdiffjs/
│   ├── vdiff.bundle.css
│   └── vdiff.bundle.min.js
├── vdiffjs-wrapper.js
├── vdiffjs-wrapper.css
└── opencv/
    └── opencv-4.5.1.js     # 約 7.3MB

spin.js / jquery.spin.js が CDN(jsDelivr)から読み込まれている部分はそのまま残しても動きます(jsDelivr は生きているため)。完全オフライン化したい場合のみ追加でミラーします。

3. 一括ダウンロードのコツ

参照アセットをループで回すときは、Wayback Machine 側のレート制限に当たって途中から HTTP 000(接続失敗)を返されることがあります。

  • リクエスト間に短いスリープを入れる(1〜3 秒程度)
  • 失敗ファイルは別配列に集めてあとで再試行する
  • --max-time90 程度に伸ばしておく
for asset in "${ASSETS[@]}"; do
  mkdir -p "$(dirname "$asset")"
  http_code=$(curl -sL --compressed --max-time 90 -w "%{http_code}" \
    "${BASE}/${asset}" -o "${asset}")
  if [[ "$http_code" != "200" ]]; then
    echo "FAIL ($http_code): $asset"
    rm -f "${asset}"
  fi
  sleep 2
done

vdiff.js だけなら 5 ファイル程度なので一瞬で終わりますが、参考までに。

4. 配置とリンク差し替え

ダウンロードしたディレクトリをそのまま配信ディレクトリに置けば /vdiff/... で配信されます(多くの静的ホスティングで素直に動きます)。

合わせて、サイト側のリンクを書き換えます。デジタル源氏物語(Vue/Nuxt 2 のクラスコンポーネント)でのパタパタ顔比較の getVDiffUrl() 例:

   getVDiffUrl(n1, n2, n3) {
     ...
-    return `http://codh.rois.ac.jp/software/vdiffjs/demo/?img1=${...}&img2=${...}`
+    return `/vdiff/?img1=${...}&img2=${...}`
   }

vdiff のラッパー(vdiffjs-wrapper.js)は location.search をそのままパースする実装なので、クエリパラメータの組み立てロジックは変更不要です。

5. ライセンスと出典表示

vdiff.js は MIT ライセンス(Core contributor: Jun HOMMA(@2SC1815J)氏)で公開されています。再配布時はライセンスと著作権表示を維持する必要があるので、各ファイルの先頭コメントに含まれている

/*
 * vdiff.js - JavaScript-based visual differencing tool
 * http://codh.rois.ac.jp/software/vdiffjs/
 * Copyright 2021 Center for Open Data in the Humanities, Research Organization of Information and Systems
 * Released under the MIT license
 */

の表示はそのまま残しています。本来の配布元は CODH なので、自サイト側の説明文等にも「ROIS-DS 人文学オープンデータ共同利用センター(CODH)の vdiff.js を、本家サイトのメンテナンス期間中に Wayback Machine からの暫定ミラーとして配信しています」のような注記を残しておくのが誠実かと思います。

おわりに

今回のミラー対応はあくまで CODH のサービス再開までの一時的な避難措置です。再開後は速やかに各リンクを本家へ戻し、ミラーは順次撤去する予定です。

CODH および core contributor の Jun HOMMA(@2SC1815J)氏が、長年にわたり良質なツール群とデータセットをオープンに公開してくださっていたからこそ、こうした暫定対応も成立しています。改めて感謝申し上げます。

参考