Skip to content

App Store のアプリプレビューを台本から作れるようにする - #134

Merged
temoki merged 2 commits into
mainfrom
film/app-previews
Sep 26, 2026
Merged

temoki merged 2 commits into
mainfrom
film/app-previews

Conversation

@temoki

@temoki temoki commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

iPhone・iPad・Mac・Vision Pro の App Store 用アプリプレビューを、ティーザー動画(#132)と同じく台本から作れるようにしました。ruby Tools/film/previews.rb を実行すると、機種ごとに 15〜20 秒の動画を Apple の仕様どおりに書き出します。

動画は英語・字幕なし・音なしです。音楽はあとから手作業で入れます。fastlane の deliver はプレビューをアップロードできないので、App Store Connect には手でアップロードします。動画ファイルはリポジトリに入れていません。

できるプレビュー

機種 解像度 長さ 中身
iPhone 886×1920 15.5 秒 パレットのシートでくり返しの中にまえへ・みぎへを足し、テンキーで 90 を 144 に変えてオレンジの星
iPad 1600×1200 18.8 秒 四角 → 144° で星 → ペンの色をドラッグで足してオレンジの星
Mac 1920×1080 20.3 秒 iPad と同じ流れを本物のカーソルで操作し、最後に Swift のコード
Vision Pro 3840×2160 16.5 秒 机の上でカメが歩きながら星を描く。ブロック・操作パネル・コードのウィンドウも映る

Apple の決まりに合わせたこと

  • 画面をそのまま撮っています。ズーム、背景、冒頭・最後のカードは入れていません(ティーザーとの違い)。Mac だけは、スクリーンショットと同じデスクトップの背景画像の上にウィンドウを置いています。
  • 操作場所を示す丸(タップの表示)は使ってよいので、iPhone と iPad には描いています。Mac は本物のカーソルとクリックの表示です。
  • 長さは 15〜30 秒です。短ければ最後のコマを伸ばし、長ければ止めます。30fps、H.264、無音の音声トラック付きです。
  • 15 秒ではゼロから組み立てる時間がないので、書類は最初からプログラムがほぼ入った状態で始めます。

構成

ティーザーの仕組みを Tools/film/ に移して分けました。

  • film.rb:録画、止まっている時間の切り詰め、タッチの描画(共通)
  • teaser.rb / previews.rb:それぞれの編集
  • window-recorder.swift:Mac のウィンドウを ScreenCaptureKit で録画
  • テスト:FilmTestCase(共通の操作)、TeaserTests、AppPreviewTests(iPhone・iPad)、MacPreviewTests

作業の手順は新しいスキル film にまとめました。内容は、Mac を撮る前にメンテナへ声をかけること、撮ったあとの確かめ方、動画の受け渡し、失敗したときの原因の見方です。仕組みと理由は Tools/film/README.md にあります。screenshots スキルには、この新しいスキルへの案内だけを残しました。release スキルには、「プレビューは fastlane で送れないので手でアップロードする」という 1 文を足しました。

アプリ本体の変更は、visionOS の開発用起動引数 -TBPlay に秒数を渡せるようにしたことだけです(下記)。

分かったこと

詳しくは Tools/film/README.md に書きました。

  • visionOS: 録画を始めてからアプリを起動すると、机の上の絵(没入空間)が開きません(毎回 TBNotReady)。そこで、絵が出てから録画を始めます。-TBPlay 6 で再生を 6 秒遅らせ、始まった瞬間を TBPlaying のログで知らせるようにしました。
  • 録画の時刻: シミュレータの録画は、復号時刻が表示時刻から最大 11 秒ずれていました。変換がそれを拾ってしまい、iPhone 版は描き終わる前にホーム画面へ切り替わりました。-fflags +igndts で直しています。ティーザーにも(目立たない形で)効いていた問題です。
  • iPhone のタップ: タップを呼んでから戻るまでが最大 1.4 秒遅れます(シートの動きを待つため)。タップの瞬間は、録画から「静止のあと最初に動いたコマ」を探して決めます。
  • Mac のウィンドウ録画: ウィンドウ単体を録画すると、左上の閉じる・最小化・拡大ボタンが macOS の紫の「共有中」ボタンに置き換わり、全コマに映ります。そこで画面全体を録画し、このアプリ以外(壁紙を含む)を除いて、ウィンドウの範囲を切り出しています。
  • Mac のテスト: テストの実行プログラムはサンドボックスの中で動くので、ログはテスト結果の添付ファイルとして受け取ります。また、Mac ではブロックの行の中の数値チップが別の要素として見えないため、行の左端と文字幅から位置を計算して押しています。
  • Mac の撮影には本人確認が要ります。 UI テストがカーソルを動かす前に、macOS がパスワードを求めます。撮影中の数分間は Mac に触れません。

確認したこと

  • 4 機種すべてを通しで撮影・合成し、メンテナが視聴済み
  • 解像度・フレームレート・音声トラックが仕様どおりであること(ffprobe)
  • UI テストのビルド(iOS シミュレータ・macOS)、visionOS アプリのビルド、swift format lint --strict
  • 撮影後に Simulator の設定(ConnectHardwareKeyboard)と自動操作モードが元に戻ること

アップロードのときに

  • Vision Pro の版は H.264 Level 5.1 です。3840×2160 は、仕様にある Level 4.0 の上限を超えるためです。App Store Connect が受け付けるかを確認する
  • ポスターフレームは、そのままだと 5 秒目(どれも途中の画面)になります。完成した星のコマを選ぶ

One preview per device class — iPhone, iPad, Mac and Vision Pro, fifteen to
twenty seconds each — made the way the teaser is: a UI test presses, a script
records and cuts. `ruby Tools/film/previews.rb` writes them to Apple's sizes
and rules, which are stricter than the website's: the screen as captured with
no zoom, no backdrop or cards, 15–30 seconds, an audio track even when it is
silence. They come out silent, for music added by hand, and are uploaded by
hand; deliver does not take previews.

The teaser's tooling moves to Tools/film/ and splits: film.rb records and
cuts, teaser.rb and previews.rb edit, and the tests share FilmTestCase.
iPhone and iPad are scripted on the simulators. Vision Pro is launched with
the screenshot rig's arguments. The Mac is scripted on this Mac and recorded
by ScreenCaptureKit (window-recorder.swift).

What it took, in Tools/film/README.md:
- `simctl io recordVideo` running through a visionOS launch keeps the
  immersive space from opening, every time. The recorder now starts once
  the sheet is up, and `-TBPlay <seconds>` holds the drawing until then;
  `TBPlaying` logs when it starts.
- The recorder's decode times drift from its presentation times, eleven
  seconds by the end of a phone run. Conversion now ignores them
  (`-fflags +igndts`). This also affected the teaser, less visibly.
- A phone's taps return up to 1.4s after the touch. Touches are now found
  in the recording, as the first break in stillness after the tap was
  called.
- A Mac window recorded as itself wears macOS's purple "sharing this window"
  control where its close, minimise and zoom buttons belong. The display is
  recorded instead, without every other application, and cropped to the
  window.
- The Mac's test runner is sandboxed, so its log comes back as a
  result-bundle attachment.
- A Mac row folds its chips into itself, so the chip is placed by
  measurement.
The how of making the teaser and the previews was a paragraph in the
screenshots skill, and the why was Tools/film/README.md. Neither said what a
reshoot actually involves:
- the maintainer has to be told before the Mac preview and type the
  password;
- the films have to be checked against the spec and on a contact sheet;
- someone has to watch them, because movement is not judged from stills;
- they have to be copied out of $TMPDIR and uploaded by hand.

That is now the film skill. The README keeps the reasons. The screenshots
skill keeps one line, because the films share its DerivedData. The release
skill notes that previews are the one part of the listing fastlane does not
carry.
@temoki
temoki merged commit f3abc20 into main Sep 26, 2026
7 checks passed
@temoki
temoki deleted the film/app-previews branch September 26, 2026 23:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant