GRFR

ファイル仕様

GRFRは、ライブラリの情報を2種類のJSONファイルで管理します。どの動画を登録したかの一覧とライブラリごとの設定を記録する「カタログファイル」と、動画1本ごとのメタデータを記録する「メタデータファイル」です。このページは、この2つのファイルの形式を定めた公開仕様です。この仕様に従えば、テキストエディタや自作のスクリプト、AIエージェントなど、GRFR以外のツールからも安全に読み書きできます。

現在の仕様のバージョンはgrfr-v1です。機械可読なスキーマ定義もJSON Schemaとして公開しています(詳しくは後述します)。

  • メタデータファイル: https://grfr.shikakun.com/schema/v1/metadata.json
  • カタログファイル: https://grfr.shikakun.com/schema/v1/catalog.json

GRFRは、正規に購入・ライセンスを取得したコンテンツや、自身が著作権を有するコンテンツを管理するためのツールです。コンテンツを取得・配信・共有する機能は持ちません。著作権を侵害して複製・配信されたコンテンツの管理には利用しないでください(利用規約第6条)。

設計の考え方

どちらのファイルもGRFRのデータベースではなく、ユーザーの資産です。仕様のすべてはこの前提から導かれています。

まず、人間が読めること。中身はごく普通のJSONで、テキストエディタで開いてそのまま編集できます。GRFRの起動中に編集しても、保存すれば変更は自動で画面に反映されます。

次に、アプリに依存しないこと。メタデータファイルにはGRFR内部の識別子を含めないため、GRFRを使わなくなってもファイル単体で意味が通ります。GRFRが動画の管理に使う内部的な識別子(ID)は、カタログファイルだけが「どのIDがどのファイルか」という対応表として持ちます。

そして、ほかのツールと共存できること。この仕様で定義していないキーがファイルに含まれていても、GRFRは保存のときにそれを消さずに残します(カタログファイルのsettingsの中の知らないキーも同様です)。

ファイルの置き場所

カタログファイルは既定で~/Movies/grfr/catalog.jsonに作られ、置き場所はアプリの設定で変えられます。メタデータファイルは動画ファイルと同じフォルダに置かれ、ファイル名は動画の拡張子を.jsonに置き換えたものです。動画のフォルダはどこにあってもかまいません。

movies/
├── sample_video.mp4    ← 動画ファイル
├── sample_video.json   ← メタデータファイル
└── sample_video.jpg    ← カバー画像

同じフォルダに拡張子だけが違う同名の動画(sample_video.mp4sample_video.movなど)があると、メタデータファイルの名前が重なってしまいます。この場合、GRFRは後から登録しようとした動画をスキップします。

共通の決まり

2つのファイルは同じ決まりで読み書きされます。文字コードはUTF-8で、トップレベルは必ずJSONオブジェクトです。GRFRが保存するときは、半角スペース2つのインデントで整形し、キーを決まった順(この仕様で定義したキーを定義順に、それ以外のキーをその後ろに辞書順)に並べ、末尾に改行を付けます。書き込みは一時ファイルへ書き出してから元のファイルと置き換える方式のため、途中で失敗しても元のファイルは壊れません。

こうした整形は、差分の読みやすさやバージョン管理のための決まりごとです。読み込むときにはこの形を求めないので、手で編集して崩れていても、次にGRFRが保存するときに整えられます。

schemaと$schema

どちらのファイルも、名前の似た2つのキーで始まります。役割は違います。

schemaは、このファイルがGRFRの仕様で書かれていることを示す印です。値は、アプリ名とバージョンを組み合わせた"grfr-v1"です。この値は仕様が定めるもので、変わりません。これらのファイルは単独で持ち出されることがあるので、アプリの外で開かれたときにも、この1行で出自とバージョンがわかるようにしています。メタデータファイルでは書き忘れても現行のバージョンとして読み込まれ、保存のときに付け加えられます(カタログファイルでは必須です。後述します)。

$schemaは、JSONの内容を機械的に検証するためのスキーマ定義の場所を指すキーです。Visual Studio Codeなど一部のテキストエディタは、このキーがあるとキー名の補完や値のチェックをしてくれます。GRFRは保存のとき、このキーが無ければそのファイルに対応する公開スキーマのURL(冒頭に挙げた2つ)を書き加えます。すでに値がある場合には書き換えません。そのため、たとえば自分のカスタムフィールドまで検証できる独自のスキーマを用意して、そちらを指すこともできます。

メタデータファイル

動画1本ごとのメタデータを記録するファイルです。

{
  "$schema": "https://grfr.shikakun.com/schema/v1/metadata.json",
  "schema": "grfr-v1",
  "title": "The Long Winter",
  "cover": "sample_video.jpg",
  "maker": "Harborlight Studios",
  "label": "Harborlight Prestige",
  "series": "The Long Winter",
  "performers": [
    "Ava Marlowe",
    "Julian Crowe",
    "Nora Keane"
  ],
  "product_id": [
    {
      "key": "imdb",
      "value": "tt8000000"
    },
    {
      "key": "tmdb",
      "value": "50000"
    },
    {
      "key": "letterboxd",
      "value": "the-long-winter"
    },
    {
      "key": "criterion",
      "value": "NW1000"
    }
  ],
  "release_date": "2008-03-14",
  "description": "A three-part family chronicle set during the hardest winter on record in a northern mill town.",
  "director": "Elena Voss",
  "tags": [
    "Drama",
    "Period",
    "Family",
    "Slow Burn"
  ],
  "rating": 5,
  "part": "1/3",
  "created_at": "2026-07-03T10:00:00+09:00",
  "updated_at": "2026-07-03T10:00:00+09:00"
}
キー 内容
$schema string スキーマ定義への参照
schema string 仕様のバージョン。常に"grfr-v1"
title string 表示タイトル
cover string / null カバー画像のファイル名
maker string / null メーカー
label string / null レーベル
series string / null シリーズ
performers stringの配列 出演者名
product_id objectの配列 サービスごとの作品ID
release_date string / null リリース日(YYYY-MM-DD
description string / null 説明文
director string / null 監督
tags stringの配列 タグ。重複と空文字は不可
rating integer / null 評価。1〜5の整数。未評価はnull
part string / null パート表記。分割された作品の何本目かを"n/m"で表す(例"1/4"
created_at string 作成日時
updated_at string 最終更新日時

どのキーも省略できます。欠けているキーは、GRFRが既定値(nullや空の配列)で補って読み込みます。以下、説明が必要なフィールドについて補足します。

title

省略したり、空文字やnullにしたりすると、動画のファイル名(拡張子を除いたもの)がタイトルとして使われます。

cover

カバー画像のファイル名です。動画と同じフォルダにあるファイルを名前だけで指します(フォルダをまたぐパスやURLは書けません)。

product_id

サービスごとの作品IDを並べる配列です。各要素はkey(サービス名)とvalue(作品ID)の2つの文字列を持ちます。サービス名は決まった語彙ではなく、ユーザーやツールが自由に決められます。

"product_id": [
  { "key": "example-store", "value": "ABC-123" },
  { "key": "example-archive", "value": "2026-0042" }
]

配列以外の値が書かれていた場合は、型が違うものとして空の配列で読み込みます。

release_dateとcreated_at・updated_at

release_date2026-01-15のような日付だけの文字列で、時刻やタイムゾーンは持ちません。

created_atupdated_atは日時の文字列です。GRFRは2026-07-03T10:00:00+09:00のように、秒までの精度でタイムゾーン付きのISO 8601形式で書き込みます。読み込むときは、小数秒が付いていたりタイムゾーンが無かったりしても受け付けます。

updated_atが変わるのは、ユーザーがメタデータを編集したときだけです。GRFRは再生位置のようなアプリ内部の状態をメタデータファイルに書かないので、動画を眺めたり再生したりしてもこのファイルは変わりません。

part

1つの作品が前編・後編などの複数ファイルに分割されているとき、その動画が全体の何本目かを"n/m"形式で表します(例: 全4本の1本目なら"1/4")。nとmは1以上の整数で、nはm以下です。

同じフォルダにあり、タイトルと総数mが一致する動画は1つのグループとして扱われ、グリッドでは常にパート番号順に並びます。この形式に一致しない値は未設定として扱われますが、書き換えられずそのまま保持されます。

カタログファイル

どの動画を登録したかの一覧と、ライブラリごとの設定を記録するファイルです。

{
  "$schema": "https://grfr.shikakun.com/schema/v1/catalog.json",
  "schema": "grfr-v1",
  "settings": {
    "sort_field": "created_at",
    "sort_ascending": false
  },
  "fields": [
    { "key": "studio", "name": "スタジオ", "type": "string" }
  ],
  "filters": [
    {
      "id": "3F2504E0-4F89-41D3-9A0C-0305E82C3301",
      "name": "未視聴",
      "match": "all",
      "rules": [
        { "field": "watched", "op": "is", "value": false }
      ]
    }
  ],
  "entries": [
    {
      "id": "1E9F0A62-6F2B-4A5B-9C3D-8F1B2C3D4E5F",
      "path": "movies/sample_video.mp4"
    }
  ]
}
キー 内容
$schema string スキーマ定義への参照
schema string 仕様のバージョン。常に"grfr-v1"
settings object ライブラリごとのアプリ設定。省略可
fields objectの配列 カスタムフィールドの宣言。省略可
filters objectの配列 保存フィルタ。省略可
entries objectの配列 登録した動画の一覧

schemaentriesの2つは必須で、どちらかが欠けているとGRFRはカタログとして読み込めません。

entries — 登録した動画の一覧

各要素はidpathの2つを持ちます。

idは、GRFRが登録のときに生成するUUIDです。サムネイルのキャッシュや再生位置と動画を結びつけるための内部的な識別子なので、手で書き換えると対応が失われます。そのままにしてください。

pathは動画ファイルの場所です。カタログファイルのあるフォルダからの相対パスが基本で、別のボリュームにあるなど相対で書けない場合だけ絶対パスになります。動画を移動・改名したときは、pathを手で書き直してかまいません。

要素にこれ以外のキーを足しても、GRFRが保存するときにidpathだけに書き直されるため残りません。動画についてのメモや独自の情報は、その動画のメタデータファイルに書いてください。

settings — ライブラリごとの設定

GRFRの設定画面やツールバーで変えられる値が、このオブジェクトに保存されます。すべて省略でき、無いキーは既定値として扱われます。範囲外の値を書いても、GRFRが既定値や近い値に丸めるだけで、エラーにはなりません。手で編集するときに使いそうなものをいくつか挙げます。

キー 既定値 内容
sort_field / sort_ascending string / boolean “created_at” / false 一覧の並び順
thumbnail_size number 240 サムネイルの大きさ(160〜480)
thumbnail_aspect string “16:9” サムネイルの縦横比。"16:9""2:3"
parts_display string “all” 分割された動画(partキー)の表示。"all"は全パートを表示、"first"はグループを1本目にまとめる
scan_extensions string “mp4,mov,m4v,avi,mkv,webm,wmv,flv,mpg,mpeg,ts,m2ts,3gp” フォルダ登録のときに動画とみなす拡張子(カンマ区切り)
cover_capture_position number 0.5 カバー画像を生成する位置(再生時間に対する割合)
seek_seconds number 10 再生中に矢印キーで飛ばす秒数

ここではすべてのキーを挙げていません。後述のJSON Schemaにすべて定義してあるので、対応するエディタなら補完でそのまま一覧できます。

fields — フィールド定義

メタデータファイルのフィールドを宣言する配列です。GRFRが標準で提供するフィールド(出演者 / メーカーなど)も、ユーザーが追加するフィールドも、すべてこのfields配列で管理します。各要素は1つのフィールドを定義します。

"fields": [
  {
    "key": "maker",
    "name": "メーカー",
    "type": "string",
    "icon": "building.2",
    "sidebar": true,
    "order": 2
  }
]
プロパティ 必須 内容
key string はい メタデータファイル上のキー名。スネークケース。$schema / schema / title / cover / product_id / release_date / description / rating / part / created_at / updated_atと、絞り込みの組み込みフィールド名duration / file_size / resolution_class / watched / missingはシステム予約キーとして使えない
name string はい 画面に表示する名前。組み込み6フィールド(performers / maker / label / series / tags / director)で既定の名前のままの場合、画面表示のみUI言語に合わせてローカライズされる(ファイル上の値は変わらない)
type string はい 値の型。string(文字列) / list(文字列の配列) / number(数値) / date(YYYY-MM-DD形式の日付) / boolean(真偽値)
icon string いいえ サイドバー行のSF Symbol名。省略時は型に応じた既定値が使われる
sidebar boolean いいえ trueにするとサイドバーにエンティティ項目として表示される。falseまたは省略時はインスペクタのみに表示
order integer いいえ サイドバー内の表示順。小さい順に並ぶ。省略時は定義配列の位置に従う

fieldsキー自体が無いカタログを開くと、GRFRが6つの既定フィールド(出演者 / メーカー / レーベル / シリーズ / タグ / 監督)をsidebar: trueで書き込みます。不要なら消してかまいません。キーが残ってさえいれば(空の配列でも)、再び書き込まれることはありません。

filters — 保存フィルタ

アプリのサイドバーから呼び出せる、名前付きの絞り込み条件です。各フィルタはid(UUIDの文字列)、name(表示名)、matchrulesを持ちます。match"all"ならすべての条件を満たすもの、"any"ならどれか1つでも満たすものが表示されます。

rulesの各要素は、調べるフィールド(field)、比べかた(op)、比べる値(value)の3つを持ちます。フィールドごとに使えるopvalueは次のとおりです。

field op value
title / maker / label / series / director contains / not_contains / is / is_not / begins_with / ends_with 文字列
performers / tags contains / not_contains 文字列
rating is / is_not / > / >= / < / <= / between 1〜5の数値、またはnull(未評価)
duration(秒) / file_size(バイト) > / >= / < / <= / between 数値
release_date / created_at on_or_after / on_or_before / between "YYYY-MM-DD"の文字列
resolution_class is / is_not "sd" / "hd" / "fhd" / "uhd4k"
watched / missing is true / false

betweenvalue[下限, 上限]の2要素の配列です。カスタムフィールドも、宣言した型に応じて同じ要領で使えます(文字列はtitle、配列はtags、数値はduration、日付はrelease_date、真偽値はwatchedと同じopが使えます)。

filtersキー自体が無いカタログを開くと、GRFRが「未視聴」「★4+」などいくつかの定番フィルタを書き込みます。不要なら消してかまいません。キーが残ってさえいれば(空の配列でも)、再び書き込まれることはありません。

手で編集して型やフィールド名を間違えたフィルタは、黙って無視されるのではなく、画面に警告つきで表示され、選ぶと0件になります。

自分のフィールドを足す

メタデータファイルの仕様で定義していないトップレベルのキーは「未知キー」として扱われ、GRFRが保存しても消えません。自作のスクリプトや外部ツールが独自のキーを書き足しても安全です。

さらに、カタログファイルのfields配列でキーに名前と型を宣言すると、そのキーは「フィールド」としてGRFRの画面に現れ、編集・検索・絞り込みに使えるようになります。sidebartrueにすればサイドバーにも表示され、エンティティとして作品数の集計や絞り込みができます。このときもメタデータファイルの側は何も変わらず、値はほかのフィールドと同じように普通のトップレベルキーとして読み書きされます。

フィールドの追加は設定画面の「フィールド」タブからGUIで行えます。テキストエディタで直接fields配列を編集することも可能で、どちらの方法で変更しても相互に反映されます。

宣言は、1つのフィールドにつき、メタデータファイルでのキー名(key)、画面に表示する名前(name)、型(type)を最低限指定します。サイドバーに表示したいときはsidebar: trueとアイコン名(icon)も指定します。たとえば「スタジオ」という文字列のフィールドと「放送年」という数値のフィールドを足すなら、次のようになります。

"fields": [
  { "key": "studio", "name": "スタジオ", "type": "string", "sidebar": true, "icon": "film" },
  { "key": "broadcast_year", "name": "放送年", "type": "number" }
]

keyは小文字とアンダースコアで書き、メタデータファイルの定義済みのキーとは別の名前にします。typeは、文字列(string)、文字列の配列(list)、数値(number)、YYYY-MM-DD形式の日付(date)、真偽値(boolean)の5種類から選べます。この宣言があると、メタデータファイルの側では次のように書けます。

{
  "$schema": "https://grfr.shikakun.com/schema/v1/metadata.json",
  "schema": "grfr-v1",
  "title": "The Long Winter",
  "studio": "Harborlight Studios",
  "broadcast_year": 2026
}

宣言する前から書かれていた値も、あとから宣言を足せばさかのぼって画面に現れます。宣言を消しても値は消えず、ただの未知キーに戻るだけです。

手で編集する・ほかのツールから読み書きする

GRFRの起動中にどちらのファイルを編集して保存しても、変更は自動で反映されます。GRFR側の操作と同時になった場合は、あとから保存されたほうが残ります。JSONとして読めない状態のファイルにGRFRが上書きすることはないので、編集の途中で壊れていても、直して保存し直せば元に戻ります。

GRFRは、壊れていたり不完全だったりするファイルにも寛容に振る舞います。キーが欠けていれば既定値で補い、型の違う値は既定値に置き換えて読み込みます。読めないファイルを消したり書き潰したりしないことが、ユーザーのデータを守ることにつながります。互換ツールを作る場合も、同じ振る舞いをお勧めします。

書き込みは、次の手順に従うとほかのツールと安全に共存できます。

  1. 既存のファイルがあれば、まずすべてのキーを読み込む
  2. 自分が管理するキーの値だけを書き換え、それ以外のキーはそのまま残す
  3. $schemaが無ければ公開スキーマのURLを書き加える(あれば触らない)
  4. メタデータファイルでは、メタデータを実際に変更した場合だけupdated_atを現在日時にする
  5. 一時ファイルに書き出してから、元のファイルと置き換える

仕様のバージョン

schemaキーのv1が仕様のバージョンで、スキーマURLのパス(/schema/v1/)と対応しています。バージョンが上がるのは、既存のキーの型や意味を変えるなど、古いファイルとの互換が保てない変更をするときだけです。キーが増えることはあり得ますが、読み込む側が知らないキーをそのまま残す決まりのため、古いツールでもファイルは壊れません。

JSON Schema

この仕様の機械可読な定義を、JSON Schema(2020-12版)として公開しています。

  • メタデータファイル: https://grfr.shikakun.com/schema/v1/metadata.json
  • カタログファイル: https://grfr.shikakun.com/schema/v1/catalog.json

前述のとおり、GRFRが保存するファイルには既定でそれぞれのURLが$schemaキーとして書き込まれるので、対応するエディタならそのまま補完と検証が効きます。カタログファイルのsettingsの全キーの定義も、スキーマに含まれています。

このスキーマ定義は検証用途として寛容に作ってあり(メタデータファイルに必須のキーはなく、カタログファイルで必須なのはschemaentriesだけで、どちらも未知キーを許容します)、GRFRが書き出す整形済みの形については、本文の「共通の決まり」と「手で編集する・ほかのツールから読み書きする」の記述を正とします。