コンテンツにスキップ
Documents for MorningStatusApp
Esc
↑↓移動↵開く⌘Jプレビュー
このページの内容

トラックリスト データ設計書

最終更新: 2026-11-07

1. 概要

releases.json にアルバム収録曲・シングルカップリングのトラックリストを追加するためのデータ設計。 プレイリスト機能(#336)において楽曲とリリースを紐付ける trackId の参照先を確立することが本設計の主目的である。


2. 背景・目的

現行の releases.json はリリースのメタ情報(タイトル・日付・フォーマット)のみを保持しており、収録曲情報がない。

目的 詳細
プレイリスト楽曲の参照先確立 PlaylistEntry.trackId が指す Track エンティティを定義する
リリース詳細画面の収録曲表示 トラック番号・曲名・ディスク番号を画面に表示できるようにする
MusicBrainz API との整合 取得可能なフィールドを洗い出し、スキーマに反映する

3. MusicBrainz API フィールドマッピング

取得エンドポイント: https://musicbrainz.org/ws/2/release/{mbid}?inc=recordings&fmt=json

レスポンス構造(関連部分)

{
  "media": [
    {
      "position": 1,
      "format": "CD",
      "tracks": [
        {
          "id": "...",
          "number": "1",
          "title": "愛の種",
          "length": 214000,
          "recording": {
            "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
          }
        }
      ]
    }
  ]
}

フィールド対応表

MusicBrainz フィールド 本設計フィールド 説明
media[].tracks[].recording.id Track.id MusicBrainz recording UUID(楽曲の安定識別子)
media[].tracks[].id Track.mbTrackId MusicBrainz track UUID(リリース上の出現位置)
media[].tracks[].number Track.trackNumber ディスク内でのトラック番号(数値化)
media[].position Track.discNumber ディスク番号(1始まり)
media[].tracks[].title Track.title 収録曲タイトル
media[].tracks[].length Track.length 曲の長さ(ミリ秒)

Track.id に recording UUID を採用する理由 同一楽曲がシングルとアルバムに重複収録される場合、track UUID はリリースごとに異なるが recording UUID は同一となる。PlaylistEntry.trackId からの参照は recording UUID の方が安定しており、クロスリリース参照(「このシングル曲はどのアルバムにも収録されている」等)が可能になる。


4. 型定義

Track インターフェース(新規追加)

export interface Track {
  /** MusicBrainz recording UUID(楽曲の安定識別子・PlaylistEntry.trackId の参照先) */
  id: string;
  /** MusicBrainz track UUID(このリリース上の出現位置の識別子)。手動登録リリースでは省略可 */
  mbTrackId?: string;
  /** ディスク内でのトラック番号(1始まり) */
  trackNumber: number;
  /** ディスク番号(1始まり。シングル等の1枚組は省略可) */
  discNumber?: number;
  /** 収録曲タイトル */
  title: string;
  /** 曲の長さ(ミリ秒。MusicBrainz に未登録の場合は省略可) */
  length?: number;
  /** 外部リンク(YouTube MV・YouTube Music・YouTube Shorts 等)。sync-discography により自動付与。未取得時は省略 */
  links?: ExternalLink[];
  /** MusicBrainz artist-credit の全要素を結合句つきで連結した名義(例: `MIMI feat. モーニング娘。`)。sync-discography で自動設定 */
  artist?: string;
  /** 主体のいずれかが広義のユニット(ユニットまたは音楽グループ)に解決できた場合の広義のユニット ID(units.json または groups.json の id と一致)。sync-discography で自動設定 */
  unitId?: string;
  /** MusicBrainz artist-credit の主体のうち先頭のアーティストの MBID。sync-discography で自動設定 */
  artistMbid?: string;
}

名義(artist-credit)の解釈

MusicBrainz の artist-credit は、アーティスト・クレジット表記名(name)・次の要素との結合句(joinphrase)の並びで1つの名義を表す。たとえば MIMI feat. モーニング娘。 は、MIMI(結合句 feat.)と モーニング娘。 の2要素で1つの名義である。sync-discography は結合句を読み取り、名義・主体・客演を次のとおり扱う(実装: lib/musicbrainz.ts)。

用語 定義
名義 全要素のクレジット表記名(省略時はアーティスト名)を、結合句を挟んで先頭から連結した文字列。Track.artist に保存する
客演 結合句が単語 feat・featuring・ft を含む(ピリオドの有無・大文字小文字・前後の空白は区別しない)箇所より後ろに並ぶアーティスト
主体 客演でないアーティスト。with・×・&・と・+・/ 等の結合句で並ぶ連名は、全員を主体とする。ただし、連続して並ぶ2人以上のアーティストが、ユニット名と一致する並びになっている場合は、その並びをまとめて1つの主体とする(後述)
主体の先頭 客演でないアーティストのうち先頭のアーティスト。その MBID を Track.artistMbid に保存する(並びをまとめた主体があっても変わらない)

ユニット名と一致する並びのまとめ方: 客演でないアーティストの並びを先頭から見ていき、各位置から始まる連続した2人以上のアーティストのクレジット表記名を、間の結合句ごと連結する(並びの最後のアーティストの後ろの結合句は含めない)。連結した文字列がユニット名(Unit.name)と一致すれば、その並びを1つの主体にまとめ、並びの次のアーティストから続きを見る。同じ位置から始まる並びが複数一致する場合は、長い並びを採る。比較は、連結した文字列とユニット名の両方に次の正規化をしてから行う。同じ名義でも曲によって表記が異なるため(例: 「仔犬ダンの物語 オリジナルサウンドトラック」の「がんばっちゃえ!」は +、「がんばっちゃえ! (Symphonic Version)」は +、No.5 の「がんばっちゃえ!」は ハロー!プロジェクト・キッズ+ と ! も全角)。

  • Unicode の NFKC 正規化で、全角の英数字・記号(!・+・?・& 等)と全角スペースを半角にする
  • 空白(半角スペース)を取り除く

まとめた主体のクレジット表記名は、一致したユニット名とする(ユニットへの紐づけは ユニット一覧機能 データ設計書 §6)。ソロアーティストへの紐づけでは、まとめた主体を、並びを構成する各アーティストの MBID でも照合する(ソロアーティスト データ設計書 §6-2)。

名義の例 主体 客演
モーニング娘。 モーニング娘。 なし
モーニング娘。 & 平家みちよ モーニング娘。、平家みちよ なし
あややム with エコハムず あややム、エコハムず なし
MIMI feat. モーニング娘。 MIMI モーニング娘。
モーニング娘。とハロー!プロジェクト・キッズ+後藤真希 モーニング娘。とハロー!プロジェクト・キッズ+後藤真希(ユニット名と一致する並び) なし
モーニング娘。とハロー!プロジェクト・キッズ+後藤真希 モーニング娘。とハロー!プロジェクト・キッズ+後藤真希(+ を + にして一致) なし
モーニング娘。とハロー!プロジェクト・キッズ+後藤真希 モーニング娘。とハロー!プロジェクト・キッズ+後藤真希(!・+ を半角にして一致) なし
高木ブーとモーニング娘。・ココナッツ娘。・藤本美貴・石井リカ 高木ブーとモーニング娘。・ココナッツ娘。・藤本美貴・石井リカ(ユニット名と一致する並び) なし
高木ブーとモーニング娘。 高木ブー、モーニング娘。 なし

ユニット・ソロアーティストへの紐づけは主体で行う(ユニットは バッチ設計書 W2「ユニット照合」、ソロアーティストは ソロアーティスト データ設計書 §6-2)。連名の2番目以降を含む主体の全アーティストは、sync-discography の実行中にだけ保持し、Track には保存しない。

備考: 従来は結合句を読まずに先頭要素だけを artist・artistMbid として保存していたため、モーニング娘。が客演のみの名義(MIMI feat. モーニング娘。)が MIMI として保存され、モーニング娘。のリリースと区別できなかった(MorningStatusApp#1697)。

トラック単位の補正(data/inputs/track-corrections.json)

MusicBrainz は有志が登録しているデータで、このアプリにとっては収集の手段・ベースである。MusicBrainz の名義から決まるユニット(Track.unitId)が実態と異なるトラックは、補正ファイルで実態のユニットを指定する。手動登録リリース(data/inputs/manual-releases.json)と同じく、リポジトリで管理する JSON ファイルとし、いつ・何を・なぜ補正したかをコミットに残す。

{
  "corrections": [
    {
      "trackId": "<Track.id(recording UUID。手動登録リリースのトラックは手動登録の ID)>",
      "unitId": "<実態の広義のユニットの id(units.json または groups.json の id と一致)>",
      "reason": "<補正の理由(例: CD のクレジットでは〜の名義)>"
    }
  ]
}
フィールド 型 必須 説明
trackId string ✅ 補正するトラックの Track.id。recording UUID は同じ録音を収録した全リリースで共通のため、補正は同じ録音を収録したすべてのリリースのトラックに当たる
unitId string ✅ 実態の広義のユニットの id。units.json または groups.json に存在する id であること
reason string ✅ 補正の理由。根拠にした資料(CD のクレジット等)を書く
  • sync-discography は、MusicBrainz からの取得と手動登録リリースのマージの後、ユニットの照合(ユニット一覧機能 データ設計書 §6)で、補正ファイルに登録したトラックは、照合の結果と既存の unitId より優先して、補正ファイルの unitId を Track.unitId にする。実行のたびに適用するため、保存済みのトラックにも当たり、REFETCH_RELEASE_IDS 等で再取得しても補正は保たれる
  • trackId に一致するトラックがない場合と、unitId が units.json にも groups.json にも存在しない場合は、警告をログに出し、その補正を適用しない
  • 補正が必要なトラックは、sync-discography が出力する登録揺れの候補(バッチ設計書 W2)から見つける

トラックの保存先リリース(複数のリリースに載る曲)

同じ録音(Track.id。recording UUID)が複数のリリースに載る場合、Track はそのうち1つのリリースにだけ保存する。保存先は、リリースの形式(Release.format)の優先度が最も高いもの(single > album > ep > compilation > live > soundtrack > other)とする。シングルの曲が、ベスト盤やコレクションではなく、シングルの収録曲になるようにするため。

  • 保存先にならなかったリリースは、収録曲のすべてが他のリリースに保存されることがあり、その場合は Track が0件のリリースとして保存される(ベスト盤・コレクション〈ハワイ限定盤を含む。いずれも compilation〉、サウンドトラック〈soundtrack〉等)。欠落ではなく、削除の対象でもない
  • 取り込みルールで取り込まないと判定されるリリース(映像のみのライブ映像・映像作品。バッチ設計書 W2「MusicBrainz API」)とは原因が異なる。Track が0件のリリースは、MusicBrainz に収録曲があり、その曲が他のリリースに保存済みなら残す
  • 再取得(REFETCH_RELEASE_IDS 等)をしても、保存先は変わらないため、0件のままになる

リリース・トラックの除外(data/inputs/discography-exclusions.json)

MusicBrainz に登録されていても、このアプリの対象外とするリリース・トラックを、除外ファイルで指定する。トラック単位の補正と同じく、リポジトリで管理する JSON ファイルとし、いつ・何を・なぜ除外したかをコミットに残す。

{
  "releases": [
    {
      "releaseId": "<Release.id(リリースグループ ID)>",
      "title": "<リリース名(ファイルを読む人のための控え)>",
      "reason": "<除外の理由(例: 歌なしの音源。MusicBrainz の注記で確認)>"
    }
  ],
  "tracks": [
    {
      "trackId": "<Track.id(recording UUID)>",
      "title": "<曲名(ファイルを読む人のための控え)>",
      "reason": "<除外の理由(例: モーニング娘。のメンバーではないアーティストの歌唱)>"
    }
  ]
}
フィールド 型 必須 説明
releases[].releaseId string ✅ 除外するリリースの Release.id
tracks[].trackId string ✅ 除外するトラックの Track.id。recording UUID は同じ録音を収録した全リリースで共通のため、同じ録音を収録したすべてのリリースから除外する
releases[].title・tracks[].title string ✅ リリース名・曲名。照合には使わない
releases[].reason・tracks[].reason string ✅ 除外の理由。根拠にした資料を書く
  • sync-discography は、除外ファイルに登録したリリース・トラックを、取得したデータから外してから照合・保存する(バッチ設計書 W2「リリース・トラックの除外」)。実行のたびに適用するため、REFETCH_RELEASE_IDS 等で再取得しても取り込まれない
  • 項目が欠けているものは、警告をログに出し、その除外を適用しない
  • 除外ファイルに登録する前から保存されているリリース・トラックは、sync-discography では消えない(保存は追加・更新だけのため)。一回限りのパッチで消す(バッチ設計書「一回限りパッチ一覧」)
  • 除外するかは、登録揺れの候補(バッチ設計書 W2)を確認して判断する。対象外とする例: 歌なしの音源(オルゴール等)のリリース、正規のリリースか確認できないリリース、モーニング娘。のメンバーではないアーティストの歌唱のトラック

ExternalLink は { type: ExternalLinkType; url: string } の形式で定義される(types/external-link.ts)。

ExternalLinkType 値 説明 付与元
youtube YouTube MV(曲詳細でインライン iframe 表示) syncTrackLinks
youtube-music YouTube Music(曲詳細の外部リンクセクションにボタン表示) syncTrackLinks
youtube-short YouTube Shorts(シングル曲のみ・Instrumental 除外・最大10件・曲詳細でインライン iframe 表示)(#774, #828) syncTrackShortLinks
spotify Spotify 手動登録
apple-music Apple Music 手動登録
line-music LINE MUSIC 手動登録
recochoku レコチョク 手動登録
mora mora 手動登録
genius Genius(歌詞リンクセクション専用。曲詳細で「Genius で歌詞を見る」リンクとして表示) syncGeniusLinks
other その他外部リンク 手動登録

Release インターフェース(tracks フィールド追加)

export interface Release {
  id: string;
  title: string;
  releaseDate: string;
  format: ReleaseFormat;
  source: string;
  sourceUrl: string;
  /** トラックリスト(sync-discography による取得後に付与。未取得時は省略) */
  tracks?: Track[];
}

tracks を省略可(optional)にすることで、既存データへの後方互換を維持する。


5. ER 図

→ docs/design/er-diagram.mdx を参照すること。

本設計で追加される Track エンティティの位置づけは ER 図の「v0.5.0 完成時点」セクションに記載。 Playlist / PlaylistEntry との関係は「v0.6.0 完成時点・全体」セクションに記載。


6. releases.json スキーマ変更

変更前

{
  "releases": [
    {
      "id": "...",
      "title": "LOVEマシーン",
      "releaseDate": "1999-09-09",
      "format": "single",
      "source": "musicbrainz",
      "sourceUrl": "https://musicbrainz.org/release/..."
    }
  ]
}

変更後(tracks フィールド追加例)

{
  "releases": [
    {
      "id": "fcd58b7d-77c0-37db-9334-5f50d92b09f1",
      "title": "LOVEマシーン",
      "releaseDate": "1999-09-09",
      "format": "single",
      "source": "musicbrainz",
      "sourceUrl": "https://musicbrainz.org/release/fcd58b7d-77c0-37db-9334-5f50d92b09f1",
      "tracks": [
        {
          "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
          "mbTrackId": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
          "trackNumber": 1,
          "title": "LOVEマシーン",
          "length": 273000
        },
        {
          "id": "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz",
          "mbTrackId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
          "trackNumber": 2,
          "title": "ザ☆ピ〜ス!",
          "length": 262000
        }
      ]
    }
  ]
}

7. PlaylistEntry への影響

playlists.json の各エントリには既に releaseId(任意)が存在する。 tracks の追加後、trackId を追加して楽曲を一意に特定できるようにする。

{
  "memberId": "makino-maria",
  "releaseId": "fcd58b7d-77c0-37db-9334-5f50d92b09f1",
  "trackId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "songTitle": "LOVEマシーン",
  "links": []
}
フィールド 必須 説明
memberId 必須 選曲したメンバーの ID
releaseId 任意 リリースが特定できる場合に付与
trackId 任意 Track.id(recording UUID)。収録曲が特定できる場合に付与
songTitle 必須 表示用の楽曲タイトル(trackId が未設定でも表示に使用)
links 必須 外部リンク(YouTube 等)

trackId を任意とする理由: tracks データが未取得のリリースや、プレイリスト上の楽曲が特定リリースに紐付かないケース(ライブ音源等)に対応するため。


8. マルチディスク対応方針

アルバム等の複数ディスク構成(CD1・CD2)は discNumber フィールドで区別する。

  • discNumber は省略可。省略時は 1 とみなす
  • trackNumber はディスク内での連番(1始まり)
  • ソート順: discNumber ASC, trackNumber ASC

9. 既存データへの影響

対象 変更内容 後方互換
types/release.ts tracks?: Track[] フィールド追加 ○ optional のため既存データは変更不要
releases.json tracks フィールドは sync-discography 実行後に付与 ○
types/playlist.ts(実装済) trackId?: string フィールド追加 ○
scripts/sync-discography.ts MusicBrainz recording API を呼び出してトラックリストを取得・保存 -

10. バージョン位置づけ

バージョン 機能 対応 Issue
v0.5.0 トラックリスト管理機能(リリース収録曲) #341(#338・#339・#340・#344)
v0.6.0 プレイリスト管理機能 #336(#328〜#335)

v0.5.0 の完成をもってプレイリスト機能(v0.6.0)の前提基盤が整う。


11. 後続 Issue との関係

Issue 依存内容
#339 Release 型定義への tracks フィールド追加 本設計書の型定義に基づいて実装
#347 Release.youtubeUrl および ExternalLink 共通型の追加 本設計書の Release 拡張方針に基づいて実装(※ youtubeUrl はその後廃止され ExternalLink[] ベースに移行済)
#340 sync-discography でのトラックリスト同期 MusicBrainz フィールドマッピング(§3)に基づいて実装
#350 sync-discography への YouTube MV URL 自動取得追加 Release.youtubeUrl フィールド(#347)に基づいて実装(現実装では Release.links を使用)
#344 リリース詳細画面の画面設計書の改訂 本設計のトラックリスト表示要件・YouTube MV リンク仕様を反映
#348 リリース詳細画面への YouTube MV リンク追加 #347・#344 完了後に実装
#330 プレイリスト機能 型定義・基盤データファイルの追加 PlaylistEntry.trackId の型定義(§7)に基づいて実装

改訂履歴

版 更新日 変更内容
1.13 2026-11-07 【実装時に追記(MorningStatusApp#1808)】Track 型の unitId と、§4 のトラック単位の補正の unitId の対応先を、units.json の id から、units.json または groups.json の id(広義のユニット)に変更(morning-status-blume#245、MorningStatusApp#1803)
1.12 2026-10-10 【実装時に追記(MorningStatusApp#1731)】§4 に「トラックの保存先リリース(複数のリリースに載る曲)」を新設し、同じ録音が複数のリリースに載る場合は形式の優先度が最も高い1つのリリースにだけ保存すること、トラックが0件のリリースが生じることを追記(MorningStatusApp#1731)
1.11 2026-10-06 【v11.3.6(MorningStatusApp#1711)】§4 に「リリース・トラックの除外(data/inputs/discography-exclusions.json)」を新設(MorningStatusApp#1711)
1.10 2026-10-03 【v11.3.1(MorningStatusApp#1706)】§4「名義(artist-credit)の解釈」のユニット名との比較の正規化を、NFKC 正規化(全角の英数字・記号・スペースを半角にする)に広げ、No.5 の ! の例を追加。名義の例の「高木ブーとモーニング娘。・ココナッツ娘。・藤本美貴・石井リカ」を全体で1つのユニットとする形に改め、高木ブーとモーニング娘。 の例を追加。§4 に「トラック単位の補正(data/inputs/track-corrections.json)」を新設(MorningStatusApp#1706, morning-status-blume#178)
1.9 2026-10-03 【v11.3.0(MorningStatusApp#1704)】§4「名義(artist-credit)の解釈」に、ユニット名と一致する連続したアーティストの並びを1つの主体にまとめる規則(空白と +・+ の表記ゆれの吸収、ソロアーティストへの紐づけでは並びを構成する各アーティストの MBID でも照合することを含む)と、その名義の例を追加(MorningStatusApp#1681, morning-status-blume#174)
1.8 2026-10-02 【v11.2.1(MorningStatusApp#1697)】§4に「名義(artist-credit)の解釈」を追加し、Track.artist・unitId・artistMbid の定義を、結合句で解釈した名義・主体に合わせて更新(MorningStatusApp#1697, #1690, #1696)
1.7 2026-05-28 Track インターフェースから shortsRefetchRequested フィールドを削除(Neon スキーマ削除 #950)
1.6 2026-05-10 Track インターフェースに artist・unitId・artistMbid フィールドを追記(Neon スキーマ追加 #853 に合わせてドキュメントを実態と一致させる)
1.5 2026-05-06 youtube-short 取得上限を 3 → 10 件に拡大し Instrumental を除外対象に追加(#828)。syncTrackShortLinks に shortsRefetchRequested フラグ駆動の再取得ロジックを追加(#823)
1.4 2026-05-06 Track インターフェースに shortsRefetchRequested フラグを追加(#824)
1.3 2026-05-06 ExternalLinkType に youtube-short を追加し、付与元ごとの一覧表を §4 に整備(#774)
1.2 2026-03-19 PlaylistEntry.trackId 仕様を §7 に追加(PR #353 レビュー指摘)
1.1 2026-03-19 ExternalLink 型を使った Track.links 設計を §4 に追加(#362・#363)
1.0 2026-03-03 初版作成(#338)

このページは役に立ちましたか?