ファイル仕様
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.mp4とsample_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_dateは2026-01-15のような日付だけの文字列で、時刻やタイムゾーンは持ちません。
created_atとupdated_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の配列 | 登録した動画の一覧 |
schemaとentriesの2つは必須で、どちらかが欠けているとGRFRはカタログとして読み込めません。
entries — 登録した動画の一覧
各要素はidとpathの2つを持ちます。
idは、GRFRが登録のときに生成するUUIDです。サムネイルのキャッシュや再生位置と動画を結びつけるための内部的な識別子なので、手で書き換えると対応が失われます。そのままにしてください。
pathは動画ファイルの場所です。カタログファイルのあるフォルダからの相対パスが基本で、別のボリュームにあるなど相対で書けない場合だけ絶対パスになります。動画を移動・改名したときは、pathを手で書き直してかまいません。
要素にこれ以外のキーを足しても、GRFRが保存するときにidとpathだけに書き直されるため残りません。動画についてのメモや独自の情報は、その動画のメタデータファイルに書いてください。
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(表示名)、match、rulesを持ちます。matchが"all"ならすべての条件を満たすもの、"any"ならどれか1つでも満たすものが表示されます。
rulesの各要素は、調べるフィールド(field)、比べかた(op)、比べる値(value)の3つを持ちます。フィールドごとに使えるopとvalueは次のとおりです。
| 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 |
betweenのvalueは[下限, 上限]の2要素の配列です。カスタムフィールドも、宣言した型に応じて同じ要領で使えます(文字列はtitle、配列はtags、数値はduration、日付はrelease_date、真偽値はwatchedと同じopが使えます)。
filtersキー自体が無いカタログを開くと、GRFRが「未視聴」「★4+」などいくつかの定番フィルタを書き込みます。不要なら消してかまいません。キーが残ってさえいれば(空の配列でも)、再び書き込まれることはありません。
手で編集して型やフィールド名を間違えたフィルタは、黙って無視されるのではなく、画面に警告つきで表示され、選ぶと0件になります。
自分のフィールドを足す
メタデータファイルの仕様で定義していないトップレベルのキーは「未知キー」として扱われ、GRFRが保存しても消えません。自作のスクリプトや外部ツールが独自のキーを書き足しても安全です。
さらに、カタログファイルのfields配列でキーに名前と型を宣言すると、そのキーは「フィールド」としてGRFRの画面に現れ、編集・検索・絞り込みに使えるようになります。sidebarをtrueにすればサイドバーにも表示され、エンティティとして作品数の集計や絞り込みができます。このときもメタデータファイルの側は何も変わらず、値はほかのフィールドと同じように普通のトップレベルキーとして読み書きされます。
フィールドの追加は設定画面の「フィールド」タブから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は、壊れていたり不完全だったりするファイルにも寛容に振る舞います。キーが欠けていれば既定値で補い、型の違う値は既定値に置き換えて読み込みます。読めないファイルを消したり書き潰したりしないことが、ユーザーのデータを守ることにつながります。互換ツールを作る場合も、同じ振る舞いをお勧めします。
書き込みは、次の手順に従うとほかのツールと安全に共存できます。
- 既存のファイルがあれば、まずすべてのキーを読み込む
- 自分が管理するキーの値だけを書き換え、それ以外のキーはそのまま残す
$schemaが無ければ公開スキーマのURLを書き加える(あれば触らない)- メタデータファイルでは、メタデータを実際に変更した場合だけ
updated_atを現在日時にする - 一時ファイルに書き出してから、元のファイルと置き換える
仕様のバージョン
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の全キーの定義も、スキーマに含まれています。
このスキーマ定義は検証用途として寛容に作ってあり(メタデータファイルに必須のキーはなく、カタログファイルで必須なのはschemaとentriesだけで、どちらも未知キーを許容します)、GRFRが書き出す整形済みの形については、本文の「共通の決まり」と「手で編集する・ほかのツールから読み書きする」の記述を正とします。