# 開発・試験・配布手順

すべてプロジェクトルートから実行します。試験範囲の選択は[運用方針](testing/test-policy.md)、入力・合否は[試験仕様](design/07-validation.md)を参照します。部品の役割は[依存物](dependencies.md)、接続やpatchの詳細は[vendor](../vendor/player/README.md)を参照し、本書は実行手順を担当します。

## 現在使える生成コマンド

同じ再生ソースから正式版・診断版・試験用を生成します。生成物にはbuildProfileを記録し、依存manifestの種別と照合します。収録内容の要件は[構成仕様](design/02-architecture.md)、配布準備の残件は[進捗](progress.md)を参照します。

| 種別 | 全体生成 | 起動 | 生成先 |
| --- | --- | --- | --- |
| 正式版 | `npm.cmd run build` | `npm.cmd start` | `artifacts/player-release-site` |
| 診断版 | `npm.cmd run build:diagnostic` | `npm.cmd run start:diagnostic` | `artifacts/player-diagnostic-site` |
| 試験用 | `npm.cmd run build:test` | `npm.cmd run start:test` | `artifacts/player-site` |

種別ごとの生成機構と収録範囲は[構成仕様](design/02-architecture.md#ビルド・配信・外部通信)を参照します。対応ソースには試験・診断のソースも保存しますが、正式版の実行資産とは区別します。

## 環境準備

Node/npm、Git、tar、npm依存を用意します。固定するsource/toolchainは[source-lock](../vendor/player/source-lock.json)、npm依存は[package-lock](../package-lock.json)を確認します。Wasm生成にはWSL Debianのmake/Python3と固定Emscripten/SDKが必要です。

開発・生成・試験にはシステムにインストールされたPATH上のNode/npmを使います。プロジェクトとしてNodeの特定版へ固定せず、子processには実行中のNodeを引き継ぎます。依存manifestの`node`と`nodeExecutable`に実際の版・実行pathを記録します。source-lockは依存ソースとWasm用SDKの固定情報です。WSL内でEmscriptenが使うNodeはSDK側の設定に従います。SDKバイナリーやnpm依存を再利用した場合は、新規コンパイルと分けて記録します。

~~~powershell
npm.cmd ci
git clone --depth 1 --branch 3.1.64 https://github.com/emscripten-core/emsdk.git tools/player-emsdk
wsl -d Debian -- bash -lc 'cd /mnt/e/dev/mediaplayerchrome/tools/player-emsdk && EMSDK_KEEP_DOWNLOADS=1 ./emsdk install 3.1.64 && ./emsdk activate 3.1.64'
~~~

SDK指定はsource-lockの固定版に対応する導入例です。プロジェクトの場所が異なる場合はWSLのpathも変更します。

[setup-wasm.sh](../scripts/player/setup-wasm.sh)は、このリポジトリーのWasm生成用環境設定スクリプトです。固定SDKをWSL側の`/var/tmp/mediaplayerchrome-emscripten-3.1.64`へ展開し、コンパイラーの設定ファイルと実行パスを用意します。通常は直接実行せず、`build`系コマンドが呼ぶ[build-wasm.sh](../scripts/player/build-wasm.sh)から読み込まれます。FFmpegのコンパイルはbuild-wasm.shがLinux側で行い、結果を`artifacts/player-deps/wasm`へ戻します。

PlaywrightブラウザーとネイティブFFmpegは生成/試験の道具です。ブラウザーは対応するPlaywrightで導入し、ネイティブFFmpegはtoolsへ配置するかFFMPEG環境変数で指定します。素材レシピの詳細は[素材生成](../scripts/fixtures/README.md)。実録画・OS/外部ストレージの提供条件は別途用意します。

source archiveはGitに含め、node_modules/tools/test-data/artifactsはローカル管理です。通常の再生成に上流checkoutの再取得は不要ですが、npm/SDK/ブラウザーの初回導入は取得が必要です。バイナリーと対応する生成設定実体・manifestを保持します。

## 生成と起動

### 正式版をローカルで確認する

~~~powershell
npm.cmd run build
npm.cmd start
~~~

`build`は型検査、依存物のWasm/bridge、プレイヤーのJavaScript、サイトと対応ソースを生成します。`start`は生成済みサイトをローカルで配信するコマンドで、生成やインターネットへの公開は行いません。ブラウザーで **http://127.0.0.1:4179/** を開きます。終了はサーバーを起動した端末でCtrl+Cです。

### 診断版をローカルで確認する

~~~powershell
npm.cmd run build:diagnostic
npm.cmd run start:diagnostic
~~~

正式版のローカルサーバーを終了してから起動し、同じローカルURLを開きます。画面の「詳細」でビルド種別が診断版であることを確認します。診断オプションを使う場合はこのサイトのURLへ付けます。正式版と診断版は生成先も別であり、正式版のURLへオプションを付けても診断版にはなりません。

試験用は冒頭の表の`build:test`・`start:test`を使います。どの種別でも、配信中の`build-info.json`が対象ディレクトリーの版・種別と一致することを確認します。試験の一時サーバーで手動確認用4179を置き換えたり停止したりしません。

### 変更箇所に応じて生成し直す

全体生成ではなく、変更の影響範囲に絞って作り直す場合の手順です。`package:*`は既存の同種別の依存物を使い、アプリとサイトを生成し直します。Wasmやbridgeの生成は行いません。

| 変更した入力 | 必要な生成 |
| --- | --- |
| 通常TSだけ | `npm.cmd run typecheck`、対象種別の`package:release`・`package:diagnostic`・`package:test`。梱包が内部でアプリを生成するため重複実行は通常不要 |
| bridge、bridgeがimportするsrc、ビルド時の分離処理 | `node scripts/player/build-deps.mjs --profile=release --js-only`等、対象種別の依存物を生成後に同種別を梱包。C入力が同じ場合だけWasmを再利用 |
| C/configure/toolchain | 対象種別の全体生成（正式版は`npm.cmd run build`、診断版は`npm.cmd run build:diagnostic`）。既存Wasm再利用で代用しない |
| 独立した確認用サイト | `node scripts/player/package-web.mjs --profile=release --output=artifacts/<対象名>`等。既存の固定測定サイトを上書きしない |

低水準スクリプト（build-deps.mjs、package-web.mjs等）でprofileを省略した場合は、既存試験との互換のためtestになります。正式版・診断版では必ず`--profile=release`または`--profile=diagnostic`を指定します。

中間アプリはartifacts/player-app-release・player-app-diagnostic・player-app、依存物はartifacts/player-deps下のrelease・diagnostic・candidateに分かれます。型検査前の生成ソースはartifacts/player-profile-source下の同種別です。既定サイトを作り直す前に、必要な固定候補とそのmanifestを保管します。再生試験中は配信ディレクトリーを再生成しません。

試験用サイトだけに /g1.html・/stage3.html・/g2-review.html・/g3.html 等のharnessを収録します。診断版は通常UIと詳細計測を持ち、試験ページ・memoryLimitProbe/adtsBoundaryは収録しません。正式版では詳細計測モジュールと診断用patchも除外します。

## 固定ソース・patchの更新と再生成

取得用checkoutはartifacts/player-upstreamへ用意します。更新対象のcommit・archive範囲をsnapshot-deps.mjsで指定し、source-lockとarchiveを生成します。cheap/commonのgitlink、FFmpeg/C entry、原文licenseの整合を確認し、必要性を再評価したpatchだけを採用します。

~~~powershell
node scripts/player/snapshot-deps.mjs
npm.cmd run build:deps -- --profile=release --clean
npm.cmd run package:release
~~~

--cleanは依存物展開先を作り直す指定で、WSL/SDKを含む全キャッシュ非依存の証明ではありません。最終再生成確認では、既存サイトや生成済みWasmへ依存しない隔離した生成先・作業領域を用い、使用したcache、toolchain、入力、出力を記録します。固定記録とbyte差が出れば差の要因を調べ、動作確認だけで同一としません。

### 隔離した生成先で確認する

低水準の生成コマンドへ`--build-root=artifacts/<専用名>`を付けると、依存物・型検査前のソース・アプリ・サイトをその配下へ分けます。子processにも引き継ぎます。指定できるのはartifactsの子ディレクトリーだけです。既存測定サイトとは別の、まだ使っていない名前を選びます。

~~~powershell
node scripts/player/build-deps.mjs --profile=release --clean --build-root=artifacts/g4-candidate
node scripts/player/package-web.mjs --profile=release --build-root=artifacts/g4-candidate
node scripts/player/verify-package.mjs artifacts/g4-candidate/player-release-site
node tests/player/browser/distribution.mjs --site=artifacts/g4-candidate/player-release-site
~~~

WasmのWSL作業領域・SDK展開先・Emscriptenコンパイルcacheも生成先に対応する専用ディレクトリーへ分けます。初回でもローカルに用意した固定SDKのdownload archiveまたは導入済みSDKを入力として使います。SDK自体のソースからのbootstrapや、ネットワーク取得なしの環境準備を証明する手順ではありません。初回/再利用の別、実行path、入力/出力hashは生成設定内のprovenanceへ保存します。[収録内容](licensing.md)。

同じ専用生成先で同じC/configure/toolchain入力を使う場合、診断・試験の依存物は`--js-only --profile=diagnostic`等で生成済みWasmを共有できます。この場合も利用したWasmのhashと元の生成記録を照合します。Wasm生成時のsource-lockを`player-deps/wasm/source-lock.json`へ保存し、旧形式のホストNode指定だけを比較対象から外します。ソース・SDK・Cコード・Wasm生成スクリプト・設定の変更はWasmの再生成が必要です。旧生成物に保存lockがない場合は、当時のlock原本を生成記録のhashと照合して用意します。別の空の生成先から再度Wasmを生成する確認と、同じ生成先のキャッシュ再利用は区別します。

SDKバイナリーだけを既存のLinux側展開先から用意する場合は、build-depsへ`--sdk-seed=/var/tmp/<既存SDK>/upstream`を指定できます。固定SDK識別子を照合して専用SDK領域へコピーし、Emscriptenのコンパイルcacheは専用領域を使用します。元の入力pathとcache再利用の有無もprovenanceへ記録します。

未改変比較はbuild-depsの--unmodifiedと対応する試験runnerの--unmodifiedを使い、候補と出力/成績を分けます。--bridge-onlyはWasm/manifest検証を完了しない部分生成なので最終確認へ代用しません。画素参照の通常hash確認は`npm.cmd run verify:g2:sources`、固定commitからの再取得は`node scripts/player/snapshot-g2.mjs --fetch`です。更新の採用理由は[設計09](design/09-dependency-changes.md)を参照します。

## 単体・ブラウザー試験

~~~powershell
npm.cmd test
npm.cmd run test:player:report
~~~

前者は単体、後者はTAP/summaryも保存する実行です。個別実行は例えば`node --test tests/player/unit/cleanup.test.mjs`。関連範囲を先に選び、最終確認の拡大条件は[試験選択方針](testing/test-policy.md)に従います。

| 対象 | package.jsonにある主なコマンド |
| --- | --- |
| 基本fixture | fixtures:g1、fixtures:stage3、fixtures:g2、fixtures:g2:acceptance |
| 入力別fixture | fixtures:aac:input、fixtures:dual-mono、fixtures:pes-tail、fixtures:input、fixtures:pes:limits（fixtures:inputのbase.tsが必要） |
| 依存物・ADTS・終了 | test:g1、test:g1:adts、test:g1:termination |
| 接続・通常再生 | test:stage3、test:g2:playback、test:playback:buffers |
| 表示・参照・循環 | test:g2:reference、test:g2:field-plan、test:g2:pixels、test:g2:queue、test:g2:native-pixels |
| 復帰・実録画 | test:g2:recovery、test:g2:recording、test:long-positions |
| 入力・故障 | test:startup、test:aac:input、test:dual-mono、test:pes-tail、test:input、test:io、test:recovery:forced |
| UI・統合・測定準備 | test:ui、test:integration、test:g3:preflight |
| 生成種別・正式版/診断版の実動作とJSON | test:build-profiles（両種別を生成後に実行。`-- --profile=release`等で選択可能） |
| 正式版JSONの異常系・保持上限・保存競合・PES容量境界 | test:release:diagnostics（正式版とPES上限fixtureを生成後に実行。`-- --site=artifacts/<候補>`で指定可能） |

コマンド名に残るg番号は既存のscript識別子です。開発ゲートの完了状態や正式ビルドの種別を示しません。各コマンドは`npm.cmd run <名前>`で実行します。入力が必要なrunnerには--sample等で対象を指定し、素材を用意してから実行します。

表示付きの例は`npm.cmd run test:ui -- --headed --chrome`、`npm.cmd run test:g2:playback -- --headed`。実録画の例は`npm.cmd run test:g2:recording -- --chrome --sample <録画.ts>`です。test:long-positionsも対象素材を指定し、位置は全長に合わせます。

test:integrationは`-- --only=T05`等の選択に対応します。資源の受入は規定反復を用い、短いmemory-trialで代用しません。長時間測定を開始する前には、利用者がPCを空けられると回答するのを待ちます。

自動Chrome/Chromium/Edgeは必ず--mute-audioを付けます。音声decode/AudioContext/PCM時計は停止せず、音量検証等の詳しい出力観測は診断・試験経路で行います。再生試験は並列にしません。headless SwiftShaderと表示付き実GPU、通常と詳細計測、focus/viewport/background引数の条件を区別します。

## 診断・ログ・成果物

正式版と診断別ビルドで保存する内容は[診断仕様](design/12-diagnostics.md)が正本です。JSONはUIの保存操作でローカルへ出力します。採取時は版・ビルド種別・有効計測・素材/環境/設定・正常時/発生時/復帰後を記録します。診断用のURLオプションを正式版の操作として案内しません。

詳細結果はartifacts/results/playerやrunnerが指定したartifacts配下へ保存します。原本/hash、対象build-info、runner/input hash、失敗・中止・欠測を保持し、会話と現行資料には必要な要点だけを載せます。確定した過去の成績は[archive](archive/README.md)、未解決は[known-issues](known-issues.md)、現在の作業は[progress](progress.md)へ分けます。

## 配布確認

配布候補を別ディレクトリーへ生成し、build-info/dependency-manifest・実行資産・対応ソース・設定実体・原文license/noticeと利用者向けリンクを照合します。HTTPSの同一origin/header/MIMEと起動を、ローカルのファイル確認とは別に検査します。対象とする実行資産をhashで固定し、途中で文書だけを再梱包した場合も実行資産の一致を確認します。

梱包時はprofile・全file hash・通常entryからのmodule/Worker参照・必要Wasm・禁止した試験/診断入口を検査します。単独照合は`node scripts/player/verify-package.mjs artifacts/player-release-site`等で実行します。この静的検査を再生や配布受入の完了とは扱いません。

対応ソースの入力hash・生成設定実体・配布manifest・protocol・原文licenseと、UI/案内ページのリンクも照合します。収録先とライセンスの適用範囲は[配布ソースの説明](licensing.md)を参照します。

`node tests/player/browser/distribution.mjs --site=artifacts/<対象サイト>`は、実資産をlocalhostで配信し、hash・header・MIME・起動・ソース/ライセンス案内・360px幅を確認します。`--tls=<証明書フォルダー>`を付けると、そのフォルダーの`cert.pem`/`key.pem`を使ったローカルHTTPSで同じ検査を行います。証明書はOSへ登録せず、ブラウザーの証明書例外をその試験contextに限って許可します。公開先の配信確認とは別の結果です。

### Cloudflare Pagesへ公開する

公開先はCloudflare Pagesの`tv-ts-player`プロジェクトです。生成済みサイトのディレクトリーをWranglerでアップロードします。ローカルの生成種別（正式版/診断版）と、Pagesの公開先（確認用/本番）は別に指定します。正式版の候補を確認用URLへ公開することもできます。

| URL | 用途と更新の仕方 |
| --- | --- |
| `https://tv-ts-player.pages.dev/` | 本番用の固定URL。本番への公開で指す内容が更新される |
| `https://a5083d1f.tv-ts-player.pages.dev/`のようなURL | 公開1回ごとに割り当てられるURL。特定の公開物を指定して確認・結果報告するために使う。先頭の文字列はPagesの識別値で、アプリの版IDやGitのcommit IDとは別 |
| `https://g4-review.tv-ts-player.pages.dev/`等 | 確認用のブランチ名に対応する別名URL。同じ名前で再公開すると新しい公開物を指す。固定した候補の再確認には上の個別URLを使う |

Wranglerの`--branch`はPagesへ伝える公開先の分類です。この操作のためにローカルのGitブランチを切り替える必要はありません。既存の本番用コマンドでは`main`を指定しています。以下の実行前に、Pages側の本番ブランチ設定が`main`であることを確認します。本番以外の名前を指定すると確認用の公開になります。URLと公開先の仕組みは[Cloudflareの説明](https://developers.cloudflare.com/pages/configuration/preview-deployments/)、アップロードの操作は[Direct Upload](https://developers.cloudflare.com/pages/get-started/direct-upload/)を参照します。

初回は公開権限のあるCloudflareアカウントで認証します。認証済みならloginは不要です。

~~~powershell
npx.cmd --yes wrangler@4.149.0 login
~~~

正式版の候補を生成して照合し、確認用に公開する例です。確認中はこのディレクトリーを作り直しません。

~~~powershell
npm.cmd run build
node scripts/player/verify-package.mjs artifacts/player-release-site
npx.cmd --yes wrangler@4.149.0 pages deploy artifacts/player-release-site --project-name tv-ts-player --branch g4-review --commit-dirty=true
~~~

表示された個別URLとローカル候補の`build-info.json`を照合し、版ID・ビルド種別・資産の一致を確認します。HTTPSでの起動、必要なHTTPヘッダー、JS/Wasmの配信形式、Worker/Workletの読み込み、再生操作・JSON保存・ソース/ライセンスへのリンクを[T16](design/07-validation.md)に従って確認します。`--commit-dirty=true`は未commitの変更を含む作業ツリーからの公開を許す指定であり、内容の確認を代行しません。

正式版の公開先は次の検査で固定候補と照合できます。`--site`にはアップロードしたディレクトリー、`--url`には実際に発行された個別HTTPS URLを指定します。

~~~powershell
node tests/player/browser/public-distribution.mjs --site=artifacts/<固定候補> --url=https://<個別公開URL>/
~~~

この検査は対応ソースを含む全配信ファイルのhash、同一origin、header/MIME、通常Chromeの起動、Worker/Workletを使う短い再生・一時停止中シーク・再開・JSON保存・停止/破棄、利用者向けリンクと360px幅を確認します。Pagesが設定として消費する`_headers`はHTTP取得対象から外し、実際の応答headerで適用を確認します。HTMLの同一origin内の拡張子省略リダイレクトを許容します。自動Chromeには`--mute-audio`を付け、PCM・時計は動かします。結果・失敗・JSON・画像は実行ごとの`artifacts/results/player/<版ID>/public-distribution/`へ保存します。長時間受入・聴感・他機種の確認を兼ねません。

診断版は`build:diagnostic`で生成し、照合対象とアップロード先ディレクトリーを`artifacts/player-diagnostic-site`へ、`--branch`を`diagnostic-review`等の本番以外の名前へ変えます。

本番の固定URLを更新するときは、配布確認を終えた正式版の**同じディレクトリー**を公開します。確認用公開後に生成し直した場合は、別候補として照合・確認し直します。

~~~powershell
node scripts/player/verify-package.mjs artifacts/player-release-site
npx.cmd --yes wrangler@4.149.0 pages deploy artifacts/player-release-site --project-name tv-ts-player --branch main --commit-dirty=true
~~~

本番URL側でも版ID・種別・配信条件を確認します。これらは公開時の手順であり、G4の配布準備が完了したという意味ではありません。現時点の残件は[進捗](progress.md)を参照します。`deploy:prototype:*`は比較基準の検証版を生成して公開するコマンドのため、正式版の公開には使いません。

## 比較基準の検証版

必要な比較だけ`npm.cmd run build:prototype`、`npm.cmd run start:prototype`、`npm.cmd run test:prototype`を使用します。正式版のsrc/生成物とprototype/既存vendor/生成物を分け、過去の試験結果を現行実装の成績へ置き換えません。素材の内容・抽出recipeは[素材生成の詳細](../scripts/fixtures/README.md)を参照します。
