本ページは IIIF Presentation API 3.0 に従って、マニフェストの作り方を解説します。
マニフェストの作り方の大まかな流れは次のとおりです。
キャンバスは IIIF ビューワの表示域を表します。基本的には、メインとなる素材(画像、動画)ごとに 1 つのキャンバスを用意します。1 つのキャンバスに複数の素材を載せることもできます(たとえば、画像と注釈テキスト、動画と字幕テキストなど)。キャンバスに載せる素材のことをアノテーションと呼びます。
ただし、素材(アノテーション)を直接キャンバスに載せていくのではなく、いったんアノテーション・ページと呼ばれるレイヤーを作成し、キャンバスに重ねていく感じになります。
マニフェスト、キャンバス、アノテーション・ページ、アノテーションはすべて、JSON-LD にもとづく JSON オブジェクトとして記述されます。
マニフェストは、IIIF ビューワに読み込ませるための全設定を統括する JSON オブジェクトです。
type
を持ち、その値は Manifest
です。id
を持ち、その値はマニフェスト自身の URI です。
https://example.org/Archive/Record1/manifest.jsonld
のようなファイル名でも構いません。URI 自体に意味があるわけではないので、「他とは重複しない識別子」になっていれば十分です。label
を持ち、その値は、このマニフェストが指し示すデータ全体のタイトルです。多言語化に対応していますが、必ず { "言語名" : [ "タイトル" ] }
の形式で書かなければなりません。items
を持ち、その値は各キャンバスの宣言です。{ "type": "Manifest", "id": "https://example.org/Archive/Record1/manifest", "label": { "en": [ "Record 1" ], "ja": [ "記録 1" ] }, "items": [ // ここに各キャンバスの宣言が置かれる
] }
実際には、マニフェストを独立ファイルにすることが多いでしょう。独立ファイル manifest.json
を作成した場合は次のようになります。
@context
で IIIF のバージョンを宣言しなければなりません。// manifest.json { "@context": "http://iiif.io/api/presentation/3/context.json", "type": "Manifest", "id": "https://example.org/Archive/Record1/manifest.json", "label": { "en": [ "Record 1" ], "ja": [ "記録 1" ] }, "items": [ // ここに各キャンバスの宣言が置かれる
] }
キャンバスは、IIIF ビューワの表示域を表す JSON オブジェクトです。必要なものは次のとおりですが、特に大事なのは items
と annotations
です。
type
を持ち、その値は Canvas
です。id
を持ち、その値はキャンバス自身の URI です。label
にタイトルを付けましょう。
label
は全体のタイトルですが、キャンバスの label
は個々のデータのタイトルです。items
に、常に表示しておきたいアノテーション・ページの宣言を並べましょう。annotations
に、表示・非表示を切り替えたいアノテーション・ページの宣言を並べます。{ "type": "Canvas", "id": "https://example.org/Archive/Research2020/canvas/1", "label": { "en": [ "Monologue 1" ], "ja": [ "モノローグ 1" ] }, "items": [ // 常に表示しておきたいアノテーション・ページの宣言が置かれる ], "annotations": [ // 表示・非表示を切り替えたいアノテーション・ページの宣言が置かれる ] }
また、必要に応じて次の宣言をします。
width
と height
でキャンバスのサイズを指定できます(単位はピクセル)。もし指定する場合は width
と height
を両方とも書かなければなりません。duration
で再生時間を指定できます(単位は秒)。{ "type": "Canvas", "id": "https://example.org/Archive/Research2020/canvas/1", "label": { "en": [ "Monologue 1" ], "ja": [ "モノローグ 1" ] }, "width": "640", "height": "480", "duration": "120", "items": [ // 常に表示しておきたいアノテーション・ページの宣言が置かれる ], "annotations": [ // 表示・非表示を切り替えたいアノテーション・ページの宣言が置かれる ] }
キャンバスを独立ファイルにする場合(たとえば canvas1.json
を作成する場合)は、冒頭に @context
を付けなければなりません。
{ "type": "Manifest", "id": "https://example.org/Archive/Record1/manifest", "label": {"en": ["Record 1" ],"ja": ["記録 1" ] }, "items": [ // ここに各キャンバスの宣言が置かれる { "type": "Canvas", "id": "https://example.org/Archive/Research2020/canvas1.json" } ] }
// canvas1.json { "@context": "http://iiif.io/api/presentation/3/context.json", "type": "Canvas", "id": "https://example.org/Archive/Research2020/canvas1.json", "label": {"en": ["Monologue 1" ],"ja": ["モノローグ 1" ] }, "width": "640", "height": "480", "duration": "120", "items": [ // 常に表示しておきたいアノテーション・ページの宣言が置かれる ], "annotations": [ // 表示・非表示を切り替えたいアノテーション・ページの宣言が置かれる ] }
素材(アノテーション)は直接キャンバスに載せられるのではなく、いったんアノテーション・ページと呼ばれるレイヤーに集積されます。
type
を持ち、その値は AnnotationPage
です。id
を持ち、その値はアノテーション・ページ自身の URI です。items
に、各アノテーションの宣言を並べましょう。{ "type": "AnnotationPage", "id": "https://example.org/Archive/Research2020/page/1", "items": [ // ここに各アノテーションの宣言が置かれる ] }
たとえば、動画の書き起こし字幕テキスト(page1.json
)と翻訳字幕テキスト(page2.json
)とを、別のアノテーション・ページとして同時に読み込むことができます。独立ファイルの冒頭には @context
を付けなければなりません。
{ "type": "Canvas", "id": "https://example.org/Archive/Research2020/canvas/1", "label": { "en": [ "Monologue 1" ], "ja": [ "モノローグ 1" ] }, "items": [ // 常に表示しておきたいアノテーション・ページの宣言が置かれる ], "annotations": [ // 表示・非表示を切り替えたいアノテーション・ページの宣言が置かれる { "type": "AnnotationPage", "id": "https://example.org/Archive/Research2020/page1.json" }, { "type": "AnnotationPage", "id": "https://example.org/Archive/Research2020/page2.json" } ] }
// 字幕テキスト/page1.json { "@context": "http://iiif.io/api/presentation/3/context.json", "type": "AnnotationPage", "id": "https://example.org/Archive/Research2020/page1.json", "items": [ // ここに各アノテーションの宣言が置かれる ] }
// 翻訳テキスト/page2.json { "@context": "http://iiif.io/api/presentation/3/context.json", "type": "AnnotationPage", "id": "https://example.org/Archive/Research2020/page2.json", "items": [ // ここに各アノテーションの宣言が置かれる ] }
素材(アノテーション)の JSON オブジェクトは次のようになります。
type
を持ち、その値は Annotation
です。id
を持ち、その値はアノテーション自身の URI です。motivation
にいずれかを記述します。
painting
。かつ、この値を持つアノテーションは、キャンバスの items
(常に表示しておきたいアノテーション・ページ)に含まれなければなりません。supplementing
。かつ、この値を持つアノテーションは、キャンバスの annotations
(表示・非表示を切り替えたいアノテーション・ページ)に含まれなければなりません。commenting
(注釈)など、Web Annotation 勧告で定義された値を使うこともできます。どの値が使えるかは IIIF ビューワによります。body
にアノテーションの実体を記述します。target
に、このアノテーションを表示させたいキャンバスの id
を繰り返します。{ "type": "Annotation", "id": "https://example.org/Archive/Research2020/annotation/1", "motivation": "painting", "body": { // アノテーションの実体 }, "target": "https://example.org/Archive/Research2020/canvas/1" }
アノテーションを独立ファイルにする場合(たとえば annotation1.json
、annotation2.json
を作成する場合)は、冒頭に @context
を付けなければなりません。
{ "type": "Canvas", "id": "https://example.org/Archive/Research2020/canvas/1", "label": {"en": ["Monologue 1" ],"ja": ["モノローグ 1" ] }, "items": [ // 常に表示しておきたいアノテーション・ページの宣言が置かれる { "type": "AnnotationPage", "id": "https://example.org/Archive/Research2020/page/1", "items": [ // ここに各アノテーションの宣言が置かれる { "type": "Annotation", "id": "https://example.org/Archive/Research2020/annotation1.json" } ] } ], "annotations": [ // 表示・非表示を切り替えたいアノテーション・ページの宣言が置かれる { "type": "AnnotationPage", "id": "https://example.org/Archive/Research2020/page/2", "items": [ // ここに各アノテーションの宣言が置かれる { "type": "Annotation", "id": "https://example.org/Archive/Research2020/annotation2.json" } ] } ] }
// annotation1.json { "@context": "http://iiif.io/api/presentation/3/context.json", "type": "Annotation", "id": "https://example.org/Archive/Research2020/annotation1.json", "motivation": "painting", "body": { // アノテーションの実体 }, "target": "https://example.org/Archive/Research2020/canvas/1" }
// annotation2.json { "@context": "http://iiif.io/api/presentation/3/context.json", "type": "Annotation", "id": "https://example.org/Archive/Research2020/annotation2.json", "motivation": "supplementing", "body": { // アノテーションの実体 }, "target": "https://example.org/Archive/Research2020/canvas/1" }
繰り返しますが、IIIF ではキャンバスに載せる素材のことをアノテーションと呼びます。アノテーションの実体は画像、動画、音声、注釈テキスト、字幕テキストなど様々です。
アノテーションの実体は body
の中に記述されます。外部ファイルを参照する場合も、参照しない場合も、必ず id
として URI を持ちます。
画像を参照する場合、
id
の URI で画像ファイルを読み込んでも構いませんし、(サーバが対応しているなら)Image API を使用することもできます。type
は Image
でなければなりません。{ "type": "Annotation", "id": "https://example.org/Archive/Research2020/annotation/1", "motivation": "painting", "body": { "id": "https://example.org/Archive/Research2020/content/image1.jpg", "type": "Image", "format": "image/jpeg", "width": "640", "height": "480" }, "target": "https://example.org/Archive/Research2020/canvas/1" }
{ "type": "Annotation", "id": "https://example.org/Archive/Research2020/annotation/1", "motivation": "painting", "body": { "id": "https://example.org/Archive/Research2020/content/image1/full/640,480/0/default.jpg", "type": "Image" }, "target": "https://example.org/Archive/Research2020/canvas/1" }
動画、音声を参照する場合、
id
の URI で動画、音声ファイルを読み込みます。type
は、動画の場合は Video
、音声の場合は Sound
でなければなりません。{ "type": "Annotation", "id": "https://example.org/Archive/Research2020/annotation/1", "motivation": "painting", "body": { "id": "https://example.org/Archive/Research2020/content/video1.mp4", "type": "Video", "format": "audio" }, "target": "https://example.org/Archive/Research2020/canvas/1" }
動画の字幕テキスト(WebVTT)を参照する場合、
id
の URI で字幕テキストファイルを読み込みます。type
は Text
でなければなりません。{ "type": "Annotation", "id": "https://example.org/Archive/Research2020/annotation/1", "motivation": "painting", "body": { "id": "https://example.org/Archive/Research2020/content/tracktext1.vtt", "type": "Text", "format": "text/vtt" }, "target": "https://example.org/Archive/Research2020/canvas/1" }
画像、動画、音声等への注釈テキストを body
に直接埋め込むこともできます。
id
として適当な URI を与えます。type
に TextualBody
を与えます。value
にテキストを記述します。このとき、format
に text/html
を指定すれば HTML を記述することもできます。language
で言語を明記することもできます。target
で繰り返したキャンバスの URI の後に、
#xywh=0,0,20,30
のように付け足すと、キャンバスの左上を原点として「(0, 0) の座標から、幅 20px、高さ 30px の範囲に対する注釈である」と指定できます。#t=20,25
のように付け足すと、「再生時間 20 秒目から 25 秒目までの範囲の注釈である」と指定できます。#xywh=0,0,20,30&t=20,25
のように両者を合体させることもできます。{ "type": "Annotation", "id": "https://example.org/Archive/Research2020/annotation/1", "motivation": "commenting", "body": { "id": "https://example.org/Archive/Research2020/content/text1", "type": "TextualBody", "format": "text/html", "language": "en", "value": "I love <strong>this</strong> portion of the movie!" }, "target": "https://example.org/Archive/Research2020/canvas/1#xywh=0,0,20,30&t=20,25" }