OAI-PMHリポジトリからPythonでレコードを全件取得する

OAI-PMHリポジトリからPythonでレコードを全件取得するスクリプトです。参考になりましたら幸いです。 import requests from requests import Request import xml.etree.ElementTree as ET # エンドポイントの定義 base_url = 'https://curation.library.t.u-tokyo.ac.jp/oai' # OAI-PMH リクエストの初回実行 params = { 'verb': 'ListRecords', 'metadataPrefix': 'curation', 'set': '97590' } response = requests.get(base_url, params=params) # 初回リクエストの準備 req = Request('GET', base_url,params=params) prepared_req = req.prepare() print("Sending request to:", prepared_req.url) # URLを出力 root = ET.fromstring(response.content) data = [] # 全データの取得 while True: # レコードの処理 for record in root.findall('.//{http://www.openarchives.org/OAI/2.0/}record'): identifier = record.find('.//{http://www.openarchives.org/OAI/2.0/}identifier').text print(f'Record ID: {identifier}') # 他のデータもここで処理可能 data.append(record) # resumptionTokenの取得と次のリクエストの実行 token_element = root.find('.//{http://www.openarchives.org/OAI/2.0/}resumptionToken') if token_element is None or not token_element.text: break # トークンがない場合、ループを終了 params = { 'verb': 'ListRecords', 'resumptionToken': token_element.text } response = requests.get(base_url, params=params) root = ET.fromstring(response.content) print("全件取得が完了しました。") print(len(data))

2024年7月14日 · 1 分 · Nakamura

Omeka SのOaiPmhリポジトリモジュールにおいて、アイテムが公開されいているサイトページのURLを取得する

概要 Omeka SのOaiPmhリポジトリモジュールにおいて、アイテムが公開されいているサイトページのURLを取得する方法に関する備忘録です。 背景 以下の記事で、OaiPmhRepositoryを使った独自語彙の作成方法を紹介しています。 https://nakamura196.hatenablog.com/entry/2021/07/25/222651 こちらも参考にしてください。 アイテムが公開されいているサイトページのURLの取得 修正前 あるカスタマイズ事例において、以下のようにサイトページのURLを取得していました。以下は、Clean Urlモジュールにおいてdcterms:identifier以外が設定されている場合にはうまくいきません。また、/s/db/record/といったハードコーディングが見られます。 if ( $item->value( "dcterms:identifier" ) ) { $this->appendNewElement($oai, 'curation:relation', self::prefix."/s/db/record/".(string)$item->value("dcterms:identifier")->value()); } 修正後 以下のようにシンプルに記述することができました。これにより、当該アイテムが複数のサイトで公開されていても対応することができます。 $sites = $item->sites(); foreach ($sites as $key => $site) { $siteSlug = $site->slug(); $this->appendNewElement($oai, 'curation:relation', $item->siteUrl($siteSlug, true)); } まとめ Omeka Sを用いたOAI-PMHリポジトリの構築にあたり、参考になりましたら幸いです。

2024年7月14日 · 1 分 · Nakamura

DrupalのREST APIを使って、複数のコンテンツを一括削除する

概要 DrupalのREST APIを使って、複数のコンテンツを一括削除する機会がありましたので、備忘録です。 参考 REST APIを使用せずにコンテンツを一括削除する方法として、以下も参考にしてください。 準備 まず、HTTP Basic AuthenticationモジュールとJSON:APIモジュールを有効化します。 さらに、REST resourcesにおいて、DELETEを有効化します。 /admin/config/services/rest 実行例 以下の自作ライブラリを使用します。 https://github.com/nakamura196/drupal_tools 以下でも処理内容をご確認いただけます。 https://nakamura196.github.io/drupal_tools/ インストール pip install git+https://github.com/nakamura196/drupal_tools .envの準備 DRUPAL_URL=http://example.org/drupal DRUPAL_USERNAME=username DRUPAL_PASSWORD=password 実行 以下のように実行します。 item_idsは、field_name(ここでは、field_item_id)に対応する一意の値のリストです。 from drupal_tools.api import DrupalAPIClient import pandas as pd def get_item_ids(): # Load a CSV file containing item ids into a DataFrame. df = pd.read_csv("./uuids.csv") item_ids = [row["asset_uuid"] for _, row in df.iterrows()] return item_ids # Call the function to get the list of item ids. item_ids = get_item_ids() # Load Drupal credentials from a .env file using the DrupalAPIClient. DRUPAL_URL, DRUPAL_USERNAME, DRUPAL_PASSWORD = DrupalAPIClient.load_credentials("../.env") # Create an instance of the DrupalAPIClient with the loaded credentials. drupal = DrupalAPIClient(DRUPAL_URL, DRUPAL_USERNAME, DRUPAL_PASSWORD) field_name = "field_item_id" nids = drupal.get_nids(item_ids, field_name) results = drupal.delete_from_nids(nids) まとめ 不具合等が含まれる可能性がありますので、使用される際は十分にご注意ください。 ...

2024年7月14日 · 1 分 · Nakamura

音声資料に関するIIIFマニフェストファイルに画像を追加する

概要 以下のAudio Presentation with Accompanying Imageを試した結果の備忘録です。 https://iiif.io/api/cookbook/recipe/0014-accompanyingcanvas/ 以下はCloverで表示した例ですが、設定した画像がプレイヤーに表示されます。 https://samvera-labs.github.io/clover-iiif/docs/viewer/demo?iiif-content=https://nakamura196.github.io/ramp_data/demo/3571280/manifest.json マニフェストファイルの記述 以下に例を格納しています。 https://github.com/nakamura196/ramp_data/blob/main/docs/demo/3571280/manifest.json 具体的には、以下のように、CanvasにaccompanyingCanvasを追加する必要がありました。 { "id": "https://nakamura196.github.io/ramp_data/demo/3571280/canvas", "type": "Canvas", "duration": 156.07999999999998, "accompanyingCanvas": { "id": "https://nakamura196.github.io/ramp_data/demo/3571280/canvas/accompanying", "type": "Canvas", "height": 1024, "width": 1024, "items": [ { "id": "https://nakamura196.github.io/ramp_data/demo/3571280/canvas/accompanying/annotation/page", "type": "AnnotationPage", "items": [ { "id": "https://nakamura196.github.io/ramp_data/demo/3571280/canvas/accompanying/annotation/image", "type": "Annotation", "motivation": "painting", "body": { "id": "https://nakamura196.github.io/ramp_data/demo/3571280/3571280_summary_image.jpg", "type": "Image", "height": 1024, "width": 1024, "format": "image/jpeg" }, "target": "https://nakamura196.github.io/ramp_data/demo/3571280/canvas/accompanying/annotation/page" } ] } ] }, わかりにくいですが、iiif_prezi3を使った記述例です。create_accompanying_canvas()によってaccompanyingCanvasを作成し、それをcanvasに関連づけています。 def add_accompanying_image(self): if self.verbose: print("Adding accompanying image") print(self.image_path) if os.path.exists(self.image_path): accompanyingCanvas = self.create_accompanying_canvas() self.canvas.accompanyingCanvas = accompanyingCanvas def create_accompanying_canvas(self): im = Image.open(self.image_path) w, h = im.size accompanyingCanvas = iiif_prezi3.Canvas(id=f"{self.prefix}/canvas/accompanying") anno_page, anno = self.create_image_annotation(w, h) accompanyingCanvas.set_hwd(height=h, width=w) accompanyingCanvas.add_item(anno_page) return accompanyingCanvas def create_image_annotation(self, width, height): anno_page = iiif_prezi3.AnnotationPage(id=f"{self.prefix}/canvas/accompanying/annotation/page") anno = iiif_prezi3.Annotation( id=f"{self.prefix}/canvas/accompanying/annotation/image", motivation="painting", body=iiif_prezi3.ResourceItem( id=f"{self.prefix}/{self.item_id}_summary_image.{self.image_format}", type="Image", format="image/jpeg", height=height, width=width ), target=anno_page.id ) anno_page.add_item(anno) return anno_page, anno (参考)画像ファイルの作成 国立国会図書館 歴史的音源(れきおん)では、画像データは提供されていないため、Dall-E 3を使用してサンプル画像を作成しました。 ...

2024年7月12日 · 1 分 · Nakamura

IIIF Audio/Visual: 複数のvttファイルを記述する

概要 IIIFを用いたAudio/Visual資料の記述について、複数のvttファイルを記述する方法に関する備忘録です。 ここでは、以下のように、日英の文字起こしテキストを記述します。 https://ramp.avalonmediasystem.org/?iiif-content=https://nakamura196.github.io/ramp_data/demo/3571280/manifest.json マニフェストファイルの記述 以下に例を格納しています。 https://github.com/nakamura196/ramp_data/blob/main/docs/demo/3571280/manifest.json 以下の記事も参考にしてください。 具体的には、以下のように複数のアノテーションとして記述することで、rampビューアによって正しく処理されました。 ... "annotations": [ { "id": "https://nakamura196.github.io/ramp_data/demo/3571280/canvas/page/2", "type": "AnnotationPage", "items": [ { "id": "https://nakamura196.github.io/ramp_data/demo/3571280/canvas/annotation/webvtt", "type": "Annotation", "label": { "ja": [ "日本語 (machine-generated)" ] }, "motivation": "supplementing", "body": { "id": "https://nakamura196.github.io/ramp_data/demo/3571280/3571280.vtt", "type": "Text", "format": "text/vtt", "label": { "ja": [ "日本語 (machine-generated)" ] } }, "target": "https://nakamura196.github.io/ramp_data/demo/3571280/canvas" }, { "id": "https://nakamura196.github.io/ramp_data/demo/3571280/canvas/annotation/webvtt/2", "type": "Annotation", "label": { "ja": [ "English (machine-generated)" ] }, "motivation": "supplementing", "body": { "id": "https://nakamura196.github.io/ramp_data/demo/3571280/3571280_en.vtt", "type": "Text", "format": "text/vtt", "label": { "ja": [ "English (machine-generated)" ] } }, "target": "https://nakamura196.github.io/ramp_data/demo/3571280/canvas" } ] } ] ... なお、Cloverでは、2つの文字起こしテキストが連続して表示されました。 ...

2024年7月12日 · 1 分 · Nakamura

ZoteroのAPIとStreamlitを使ったアプリ開発

概要 ZoteroのAPIとStreamlitを使ったアプリを試作しました。 https://nakamura196-zotero.streamlit.app/ 本記事は、このアプリ開発におけるメモです。 Streamlit 以下の記事がとても参考になりました。 https://qiita.com/sypn/items/80962d84126be4092d3c ZoteroのAPI ZoteroのAPIについて、以下で説明されています。 https://www.zotero.org/support/dev/web_api/v3/start 今回は上記のページで紹介されている以下のライブラリを使用しました。 https://github.com/urschrei/pyzotero APIの利用にあたっては、personal library IDやAPI keyを取得する必要がありますが、READMEのQuickstartの手順に従うと、それらを取得することができました。 以下は、API keyを発行した際の画面です。 Streamlitを用いた開発 以下のリポジトリでソースコードを公開しています。 https://github.com/nakamura196/zotero_streamlit 機密情報 機密情報は、/.streamlit/secrets.tomlというファイルを作成し、そこに記載するようでした。.gitignoreに記載することも忘れないようにしてください。 [zotero] library_id="xxx" library_type="user" api_key="xxx" そして、以下のように呼び出すことができました。 def init_zotero(): library_id = st.secrets["zotero"]["library_id"] library_type = st.secrets["zotero"]["library_type"] api_key = st.secrets["zotero"]["api_key"] return zotero.Zotero(library_id, library_type, api_key) Zoteroライブラリのコレクション一覧の取得 以下ので、Zoteroライブラリからコレクションの一覧を取得することができました。 def fetch_collections(zot): """ Zoteroライブラリからコレクション一覧を取得する """ collections = zot.collections() # 各コレクションからタイトルとキー(ID)を取得 collection_list = [{"name": collection['data']['name'], "key": collection['data']['key']} for collection in collections] return collection_list コレクション内のアイテムの取得 以下でコレクション内のアイテムを取得できました。itemTypeがattachmentのものはスキップする処理を加えています。 # 文献データをDataFrameに変換 def create_df(zot, collection_id): if not collection_id: return pd.DataFrame() try: items = zot.collection_items(collection_id) rows = [{ 'title': item['data']['title'], "itemType": item['data']['itemType'], "creators": ", ".join(f"{creator['firstName']} {creator['lastName']}" for creator in item['data'].get('creators', [])), "date": item['data'].get('date', "") } for item in items if item['data']['itemType'] != "attachment"] return pd.DataFrame(rows) except Exception as e: st.error(f"Failed to load items from collection: {e}") return pd.DataFrame() メタタグ設定 以下のような形で、タイトルなどのページ設定を行うことができました。 ...

2024年7月11日 · 1 分 · Nakamura

字幕付きの音声ファイルをIIIFビューアで表示する

概要 字幕付きの音声ファイルをIIIFビューアで表示する機会がありましたので、備忘録です。 国立国会図書館 歴史的音源で公開されている「日本のアクセントと言葉調子(下)」を対象に、OpenAIのSpeech to textを使用しています。文字起こし結果には誤りが含まれていますので、その点はご注意ください。 以下は、Rampでの表示例です。 https://ramp.avalonmediasystem.org/?iiif-content=https://nakamura196.github.io/ramp_data/demo/3571280/manifest.json 以下は、Cloverでの表示例です。 https://samvera-labs.github.io/clover-iiif/docs/viewer/demo?iiif-content=https://nakamura196.github.io/ramp_data/demo/3571280/manifest.json 以下は、Aviaryでの表示例です。こちらについては、残念ながら今回使用したマニフェストファイルの形式では、文字起こしテキストは表示できませんでした。 https://iiif.aviaryplatform.com/player?manifest=https://nakamura196.github.io/ramp_data/demo/3571280/manifest.json 以下、これらのマニフェストファイルの作成方法について紹介します。 mp4ファイルの準備 以下の記事を参考に、mp4ファイルを取得します。 vttファイルの作成 OpenAIのAPIを使用して、文字起こしを行います。 from openai import OpenAI client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) audio_file= open(output_mp4_path, "rb") transcript = client.audio.transcriptions.create( model="whisper-1", file=audio_file, response_format="vtt") with open(output_vtt_path, "w", encoding="utf-8") as file: file.write(transcript) マニフェストファイルの作成 不完全なコードですが、以下のようなプログラムによって、マニフェストファイルを作成します。 from iiif_prezi3 import Manifest, AnnotationPage, Annotation, ResourceItem, config from moviepy.editor import VideoFileClip def get_video_duration(filename): with VideoFileClip(filename) as video: return video.duration config.configs['helpers.auto_fields.AutoLang'].auto_lang = "ja" duration=get_video_duration(mp4_path) manifest = Manifest(id=f"{prefix}/manifest.json", label=label) canvas = manifest.make_canvas(id=f"{prefix}/canvas", duration=duration) anno_body = ResourceItem(id=mp4_url, type="Sound", format="audio/mp4", duration=duration) anno_page = AnnotationPage(id=f"{prefix}/canvas/page") anno = Annotation(id=f"{prefix}/canvas/page/annotation", motivation="painting", body=anno_body, target=canvas.id) anno_page.add_item(anno) canvas.add_item(anno_page) # VTT URLを追加 vtt_body = ResourceItem(id=vtt_url, type="Text", format="text/vtt") vtt_anno = Annotation( id=f"{prefix}/canvas/annotation/webvtt", motivation="supplementing", body=vtt_body, target=canvas.id, label = "WebVTT Transcript (machine-generated)" ) vtt_anno_page = AnnotationPage(id=f"{prefix}/canvas/page/2") vtt_anno_page.add_item(vtt_anno) canvas.annotations = [vtt_anno_page] with open(output_path, "w") as f: f.write(manifest.json(indent=2)) ライブラリとして、iiif-prezi3を使用しています。以下の記事も参考にしてください。 ...

2024年7月10日 · 1 分 · Nakamura

mdx.jpのオブジェクトストレージに複数ファイルをアップロードする

概要 mdx.jpのオブジェクトストレージに複数ファイルをアップロードする方法の備忘録です。以下の動画を参考にしています。 https://youtu.be/IN_4NS9hO2Y 準備 macOSで作業します。 brew install s3cmd 設定(内容は動画を確認してください。) s3cmd --configure 一括登録(同期) 以下は、ローカルのrekionフォルダ内のファイルをs3://rekion/iiif/と同期します。 s3cmd sync docs/rekion/ s3://rekion/iiif/ --exclude '.DS_Store' 参考 find . -name '.DS_Store' -type f -delete aclの一括変更 s3cmd setacl s3://rekion/iiif/ --acl-public --recursive 注意(corsの許可) 以下のxmlファイルを用意して、corsの許可を試みました。 <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedHeader>*</AllowedHeader> </CORSRule> </CORSConfiguration> ただし、以下の結果となり、この方法ではcorsの許可ができませんでした。 s3cmd setcors cors.xml s3://rekion/ ERROR: S3 error: 501 (NotImplemented): A header or parameter you provided implies functionality that is not implemented. 設定方法について、引き続き調べたいと思います。 まとめ mdx.jpのオブジェクトストレージの利用にあたり、参考になりましたら幸いです。

2024年7月9日 · 1 分 · Nakamura

国立国会図書館 歴史的音源で公開されている音声をmp4に変換する

概要 国立国会図書館 歴史的音源(以下、れきおん)で公開されている音声をmp4に変換する機会がありましたので、備忘録です。 れきおんの提供形式 れきおんでは、m3u8形式のファイルが公開されていました。 例えば、以下の「講演:道徳、経済合一論(一)Union of Morality of Economy」を確認してみます。 https://rekion.dl.ndl.go.jp/pid/3574643 開発者ツールなどで確認すると、以下のURLからアクセスできることが確認できます。 https://rekion.dl.ndl.go.jp/contents/3574643/83389ec6-2b45-4fdd-88d6-89628841039f/317d6ab4-32ec-4085-88e6-cfe36ffd34c3/317d6ab4-32ec-4085-88e6-cfe36ffd34c3_hls.m3u8 このURLを構成するIDなどは、以下のAPIの返却結果の中で確認できました。 https://rekion.dl.ndl.go.jp/api/item/search/info:ndljp/pid/3574643 pidから上記のURLを取得するAPIの開発 上記のJSONを処理することで、m3u8ファイルのURLを取得します。 この部分をAPI化したので、試していただけますと幸いです。 https://iiif-demo-next.vercel.app/api/rekion/3574643 以下のような結果が得られます。 { "data": { "type": "rekion", "id": "3574643", "attributes": { "title": "講演:道徳、経済合一論(一)Union of Morality of Economy", "url": "https://rekion.dl.ndl.go.jp/pid/3574643", "hls": "https://rekion.dl.ndl.go.jp/contents/3574643/83389ec6-2b45-4fdd-88d6-89628841039f/317d6ab4-32ec-4085-88e6-cfe36ffd34c3/317d6ab4-32ec-4085-88e6-cfe36ffd34c3_hls.m3u8" } } } ソースコードは以下です。 https://github.com/nakamura196/iiif-demo-next/blob/main/src/app/api/rekion/[id]/route.ts ffmpegを使ってmp4に変換する 以下のようなコマンドにより、m3u8ファイルをmp4形式に変換できました。 ffmpeg -i "https://rekion.dl.ndl.go.jp/contents/3574643/83389ec6-2b45-4fdd-88d6-89628841039f/317d6ab4-32ec-4085-88e6-cfe36ffd34c3/317d6ab4-32ec-4085-88e6-cfe36ffd34c3_hls.m3u8" -c copy 3574643.mp4 まとめ 音声ファイルの利用にあたり、参考になりましたら幸いです。

2024年7月9日 · 1 分 · Nakamura

Rampをカスタマイズする

概要 Rampのカスタマイズ方法に関する備忘録です。カスタマイズの結果、以下のように、UIの一部を日本語化し、メディアプレイヤーとメタデータおよび文字起こしを左右に並べて表示します。また、クエリパラメータtを使って、音声の再生開始時間を指定できるようにします。 例えば、以下のURLから、140秒時点から再生することができます。 https://ramp-iiif.vercel.app/?iiif-content=https://nakamura196.github.io/ramp_data/demo/3571280/manifest.json&t=140 以下がカスタマイズ前です。 セットアップ 以下の記事の参考にしてください。 カスタマイズ 音声の再生開始時間の指定 以下のマニュアルにおいて、startCanvasTimeプロパティが使えることがわかります。 https://samvera-labs.github.io/ramp/#!/IIIFPlayer そこで、以下のindex.jsファイルに対して、startCanvasTimeをクエリパラメータから取得する処理を追加します。 import React from 'react'; import ReactDOM from 'react-dom'; import App from './app'; // import config from './config'; const manifestURL = () => { const params = new URLSearchParams(window.location.search); // let url = `${config.url}/manifests/${config.env}/lunchroom_manners.json`; let url = "https://nakamura196.github.io/ramp_data/demo/3571280/manifest.json" if (params.has('iiif-content')) { url = params.get('iiif-content'); } return url; }; const startCanvasTime = () => { const params = new URLSearchParams(window.location.search); if (params.has('t')) { return parseFloat(params.get('t')); } return 0; } ReactDOM.render(<App manifestURL={manifestURL()} startCanvasTime={startCanvasTime()} />, document.getElementById('root')); そして、app.jsに対して、startCanvasTimeプロパティを与えます。これにより、クエリパラメータから、メディアの再生開始時間を指定できます。 ... <IIIFPlayer manifestUrl={manifestUrl} startCanvasTime={canvasTime} > ... 日本語化およびレイアウトの変更 上記と同様、demo/app.jsファイルを編集することで、日本語化およびレイアウトの変更を行うことができます。 Vercelへのデプロイ Build & Development Settingsを以下のように指定します。 Build Commandにnpm run demo:build、Output Directoryにdemo/distを設定します。 また、Node.js Versionを18.xにする必要がありました。20.xの場合、パッケージのインストール時にエラーが発生しました。 まとめ Rampの開発に関わる方々に感謝いたします。RampおよびIIIF Presentation API v3の利用にあたり、参考になりましたら幸いです。 ...

2024年7月9日 · 1 分 · Nakamura

Rampをローカルで起動する

概要 Rampをローカルで起動してみましたので、備忘録です。 背景 Rampは以下のように説明されています。 Interactive, IIIF powered audio/video media player React components library. (日本語訳)インタラクティブな、IIIF対応のオーディオ/ビデオメディアプレイヤーReactコンポーネントライブラリ 以下のGitHubリポジトリでソースコードが公開されています。 https://github.com/samvera-labs/ramp 起動 以下で起動できました。 git clone https://github.com/samvera-labs/ramp pnpm i pnpm demo 以下に記載があります。 https://github.com/samvera-labs/ramp?tab=readme-ov-file#styleguidist-development 以下の場合は、スタイルガイドのページが表示されますので、ご注意ください。 pnpm dev まとめ 参考になりましたら幸いです。

2024年7月8日 · 1 分 · Nakamura

URLの引数で指定したIIIFマニフェストに対して、Mirador 3のannotationsプラグインを試す

概要 URLの引数で指定したIIIFマニフェストに対して、Mirador 3のannotationsプラグインを試すことができるデモページを用意しました。 https://mirador-annotations.vercel.app/ iiif-contentまたはmanifest引数を使用することで、指定したIIIFマニフェストを対象にすることができます。 https://mirador-annotations.vercel.app/?iiif-content=https://dl.ndl.go.jp/api/iiif/1301543/manifest.json 本記事は、このデモページの作成に関する備忘録です。 背景 Mirador 3向けのアノテーション付与プラグインとして、mirador-annotationsがあります。 https://github.com/ProjectMirador/mirador-annotations 以下の記事で使い方の例を紹介しています。 そして、以下のデモページがすでに用意されていますが、URLの引数にIIIFマニフェストファイルを指定する機能は提供されていません。 https://mirador-annotations.netlify.app/ フォークと修正 URLの引数にIIIFマニフェストファイルを指定する機能の追加にあたり、上記のリポジトリをクローンしました。 https://github.com/nakamura196/mirador-annotations そして、以下の修正を加えました。 https://github.com/nakamura196/mirador-annotations/commit/18848ccb1fa51df821335ed76e7b9f4e974527d0 特に、以下の修正を加えています。 ... var params = new URL(document.location).searchParams; var manifest = params.get('iiif-content') || params.get('manifest') || 'https://iiif.harvardartmuseums.org/manifests/object/299843' var windows = []; if (manifest) { windows.push({ manifestId: manifest }); } ... これは、以下の実装を参考にしています。iiif-contentまたはmanifest引数でIIIFマニフェストファイルを参照するようでした。 https://projectmirador.org/embed/?iiif-content=https://iiif.io/api/cookbook/recipe/0001-mvm-image/manifest.json Vercelへのデプロイ設定 フォークしたリポジトリのソースコードをビルドした結果を、Vercelにデプロイしています。 デプロイにあたり、以下のような修正を加えました。 Output Directory、Install CommandおよびNode.jsのVersionを16.xに変更しています。 まとめ Mirador 3の利用にあたり、参考になりましたら幸いです。

2024年7月7日 · 1 分 · Nakamura

mdx.jpのオブジェクトストレージとCantaloupe Image Serverを使ってIIIF画像を配信する

概要 mdx.jpのオブジェクトストレージとIIIFイメージサーバの一つであるCantaloupe Image Serverを使ってIIIF画像を配信する方法に関する備忘録です。 背景 以下の記事で、mdx.jpのオブジェクトストレージを使った画像の配信方法について紹介しました。 また以下の記事で、Cantaloupe Image Serverで、Amazon S3に格納した画像を配信する方法について紹介しました。 これらを組み合わせることにより、デジタルアーカイブにおけるIIIF画像配信コストの課題の解決を目指します。 方法 以下の記事で紹介したDocker版Cantaloupeを使用します。 以下のリポジトリから、ソースコードをダウンロードいただけます。 https://github.com/nakamura196/docker_cantaloupe_s3 同梱されている.env.sampleを.envファイルにリネームし、設定を変更します。 # aws s3 CANTALOUPE_S3SOURCE_ENDPOINT= # mdx.jp # CANTALOUPE_S3SOURCE_ENDPOINT=https://s3ds.mdx.jp CANTALOUPE_S3SOURCE_ACCESS_KEY_ID= CANTALOUPE_S3SOURCE_SECRET_KEY= CANTALOUPE_S3SOURCE_REGION= CANTALOUPE_S3SOURCE_BASICLOOKUPSTRATEGY_BUCKET_NAME= ポイントはCANTALOUPE_S3SOURCE_ENDPOINTです。ここに、https://s3ds.mdx.jpを与えて、取得したACCESS_KEY_IDやSECRET_KEY、作成したBUCKET_NAMEやREGIONを設定します。 デモ 冒頭の記事でも使用した、いらすとやさんの画像を利用します。 https://www.irasutoya.com/2016/09/blog-post_810.html 以下、上記でアップロードした同じ画像ファイルを、Cantaloupeを使って配信している例です。 info.json https://cantaloupe.aws.ldas.jp/iiif/3/baby_asia_boy.png/info.json グレー化: full/max/0/gray.jpg https://cantaloupe.aws.ldas.jp/iiif/3/baby_asia_boy.png/full/max/0/gray.jpg なお、Cantaloupeを使って画像配信を行う場合には、上記の記事で実施したACLの設定(EveryoneにRead権限を与える)は不要です。デフォルトの設定を使用することで、オブジェクトストレージ上の画像ファイルへの直接アクセスは不可としつつ、Cantaloupeを介したアクセスのみを許可できるかと思います。 以下の記事で紹介したようなCantaloupe側のAccess Control設定を組み合わせることで、アクセス制御を実現することになるかと思います。 まとめ Amazon S3に格納した画像をIIIF画像として配信する方法として、以下の方法もあります。これが、Amazon S3以外のオブジェクトストレージにも対応しているのか、今後調査してみたいと思います。 IIIF画像の配信にあたり、参考になりましたら幸いです。

2024年7月7日 · 1 分 · Nakamura

mdxのオブジェクトストレージを使用する(Cyberduckの利用)

概要 mdxのオブジェクトストレージを使用する機会がありましたので、備忘録です。 https://mdx.jp/ 料金 2024年度の料金は以下のようになっています。 https://mdx.jp/guide/charge 1GBあたり、0.01ポイント(円)/日となっており、おおよそ1GBあたり、0.3円/月となっています。 申請方法 & s3cmdを用いた使い方 以下の公式チュートリアル動画が参考になりました。 https://www.youtube.com/watch?v=IN_4NS9hO2Y Cyberduckを使う 上記の動画ではコマンドラインツールによるファイル操作方法が紹介されています。 ここでは、Cyberduckを使用して、GUIを使ってファイル操作を行います。 AWS S3に対するCyberduckの操作方法を以下の記事で紹介しています。以下の方法を参考に、mdxのオブジェクトストレージに接続してみます。 接続設定 「新規接続」から接続設定を行います。 「Amazon S3」を選択して、サーバに「s3ds.mdx.jp」を入力します。 そして、発行された「アクセスキーID」および「シークレットアクセスキー」を入力します。 バケットの作成 右クリック > 「新規フォルダ」でバケットを作成できます。 ファイルのアップロード 以下のいらすとやさんの画像を使用します。 https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNuMuIaXnIW5QJXkLiV1ojUeUiIwNQF1O0lp2LgG2LGJUbIU8j4bFAyLyKq3BiYp53p0Yc8AtMsEykJAQgEx4SJyFvKY4OyNeDBFopPb4lnV7_wtZNkr91qwj6-m-8s-sl1aadYMhrpuoI/s800/baby_asia_boy.png 「satoru196」フォルダにドラッグ&ドロップでアップロードすることができます。 上述した公式チュートリアルでも言及されていますが、このままでは以下のURLにアクセスしても、表示ができません。 https://s3ds.mdx.jp/satoru196/baby_asia_boy.png 以下のようなエラーコードが表示されます。 <Error> <script/> <Code>AccessDenied</Code> <Message>Access Denied</Message> <RequestId>...</RequestId> <HostId>00000000000000000</HostId> </Error> ACLの変更 ファイルを右クリックして、「情報」をクリックします。 以下のように、Everyoneを選択して、 READ権限を付与します。 この結果、以下のURLから画像を閲覧することができます。 https://s3ds.mdx.jp/satoru196/baby_asia_boy.png まとめ mdxのオブジェクトストレージを活用することで、様々な用途がありますが、例えばメディアを安価に公開することができそうです。特に、デジタルアーカイブにおけるメディアの公開元として、有力なインフラになり得るかと思います。 mdxのs3互換のオブジェクトストレージの利用にあたり、参考になりましたら幸いです。

2024年7月6日 · 1 分 · Nakamura

Mirador 3でScroll Viewを使う

概要 Mirador 3でScroll Viewを使う方法についての備忘録です。 以下、「鹿児嶋征討記之内 高瀬口河通ノ戦争野津公聯隊旗を取返ス図(国立国会図書館所蔵)」を例としています。 このIIIFマニフェストは3つのキャンバス(画像)から構成されており、通常の表示方法(Single, 単一モード)では、画像ごとに表示されます。 これを3つ繋げて表示することを目指します。 デモ 以下からお試しいただけます。 https://nakamura196.github.io/mirador-multi-image/ IIIFマニフェストファイルについては、国立国会図書館で公開されているIIIFマニフェストファイルを一部変更しています。 変更前 https://dl.ndl.go.jp/api/iiif/1301543/manifest.json 変更後 https://nakamura196.github.io/mirador-multi-image/manifest.json 変更箇所として、今回の記事の目的であるScroll表示と直接関係がありませんが、画像が右から左に表示されるように、"viewingDirection": "right-to-left"を追加しています。 Miradorの設定 Mirador 2では事前設定なしにScroll Viewが使えましたが、Mirador 3のデフォルト設定では、Scroll Viewは無効化されているようでした。 https://projectmirador.org/embed/?iiif-content=https://nakamura196.github.io/mirador-multi-image/manifest.json そこで、Mirador 3の初期設定を以下のように修正します。 https://github.com/nakamura196/mirador-multi-image/blob/main/docs/index.html const config = { id: "mirador", windows: [ { manifestId: "./manifest.json", }, ], language: "ja", window: { sideBarOpenByDefault: true, defaultSideBarPanel: "info", defaultView: "scroll", views: [{ key: "single" }, { key: "gallery" }, { key: "scroll" }], }, }; Mirador.viewer(config); ポイントは、views: [{ key: "single" }, { key: "gallery" }, { key: "scroll" }]です。ここで、Scroll Viewを追加することで、以下のように選択肢として表示されるようになりました。 参考 defaultView未指定時のバグ デフォルト表示を未指定の場合、上記の例ではSingle(単一)表示が使用されますが、その状態からScroll Viewボタンを押すと、表示がうまく切り替わらないケースがありました。 この問題について、上記のように、defaultView: "scroll"を設定しておくことで回避できました。根本的な解決方法は改めて調査したいと思います。 ...

2024年7月6日 · 1 分 · Nakamura

Docker + Traefikで運用するDrupalのリバースプロキシ設定

概要 以下の記事で紹介したDocker + Traefikを用いて、HTTPS化したDrupalを運用していました。 この時、Drupalのデフォルト設定の場合、以下のように、httpのURLが設定されていました。 この問題として、以下の記事になるように、例えばGoogleアカウントでログインするようにした際、リダイレクトURLがhttpから始まるURLとなり、Google Cloud コンソールにはhttpsから始まるURLを入力する必要があり、この齟齬によって、認証ができないケースなどがありました。 https://drupalfan.com/【drupal】googleアカウントでログインできるようにする/ 本記事では、この問題に対処するための方法についてメモします。 方法 以下の記事が参考になりました。 https://www.58bits.com/blog/canonical-urls-https-and-drupal-89-reverse-proxy-settings 以下の3行を追加することで、Drupalの内部的にもhttpsから始まるURLに設定されました。 ... $settings['reverse_proxy'] = TRUE; $settings['reverse_proxy_addresses'] = array($_SERVER['REMOTE_ADDR']); $settings['reverse_proxy_trusted_headers'] = \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_FOR | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PROTO | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PORT; ... まとめ 考慮不足の点があるかもしれませんが、参考になりましたら幸いです。

2024年7月4日 · 1 分 · Nakamura

Traefikでhttpsにリダイレクトさせる

概要 以下の記事でTraefikを使ったhttps化したコンテナの運用例を紹介しました。 ただ、(現在は修正済み)http接続をhttps接続にリダイレクトする設定が漏れており、80ポートにアクセスすると、not foundになっていました。 この点の修正方法に関する備忘録です。 変更前 log: # level: DEBUG entryPoints: web: address: :80 websecure: address: :443 api: dashboard: true providers: docker: exposedByDefault: false certificatesResolvers: myresolver: acme: email: aaa@bbb storage: /acme.json caServer: https://acme-v02.api.letsencrypt.org/directory # caServer: https://acme-staging-v02.api.letsencrypt.org/directory httpChallenge: entryPoint: web 変更後 log: # level: DEBUG entryPoints: web: address: :80 http: redirections: entryPoint: to: websecure schema: https permanent: true websecure: address: :443 api: dashboard: true providers: docker: exposedByDefault: false certificatesResolvers: myresolver: acme: email: na.kamura.1263@gmail.com storage: /acme.json caServer: https://acme-v02.api.letsencrypt.org/directory # caServer: https://acme-staging-v02.api.letsencrypt.org/directory httpChallenge: entryPoint: web entryPointsの部分について、以下のようにリダイレクトの設定を追加しています。 ...

2024年7月4日 · 1 分 · Nakamura

IIIF対応ビューアの一覧の調査例

概要 IIIF対応のビューアの一覧にあたり、調べてみた例を共有します。不足している点も多いかと思いますが、参考になりましたら幸いです。 Name URL Icon Mirador https://projectmirador.org/embed/?iiif-content= mirador3.svg Universal Viewer https://uv-v3.netlify.app/#?manifest= uv.jpg Annona https://ncsu-libraries.github.io/annona/tools/#/display?url= annoa.png Clover https://samvera-labs.github.io/clover-iiif/docs/viewer/demo?iiif-content= clover.png Glycerine Viewer https://demo.viewer.glycerine.io/viewer?iiif-content= glycerine.jpg IIIF Curation Viewer http://codh.rois.ac.jp/software/iiif-curation-viewer/demo/?manifest= icp-logo.svg Image Annotator https://www.kanzaki.com/works/2016/pub/image-annotator?u= ia-logo.png TIFY https://tify.rocks/?manifest= tify-logo.svg 参考 以下のIIIF 3.0 Viewer Matrix などが参考になりました。 https://iiif.io/api/cookbook/recipe/matrix/#basic-recipes

2024年7月4日 · 1 分 · Nakamura

Chromeでサイズが大きい動画が再生できない

概要 Chromeにおいて、サイズが大きい動画が再生できないことがありました。一方、Safariでは再生できました。 開発者ツールで確認すると、ダウンロードがキャンセルされていました。 ビューア部分は以下のようになっています。 <video controls="controls" preload="none" style="width: 620px; height: 465px;" width="100%" height="100%"> <source src="https://omeka.aws.ldas.jp/files/original/c486fe4ae8d926034678fa11b0d6b2fd55b0e695.mp4" type="video/quicktime" title="undefined"> </video> このHTMLは、以下の記事で紹介した、Omeka S + IIIF Serverの組み合わせによって作成されたものです。 原因 先ほどのhtmlを確認すると、type="video/quicktime"となっており、拡張子はmp4となっていますが、中身は異なる(movファイル?)ことがわかります。 おそらく動画の拡張子のみが変更され、Omeka Sに登録された際、Omeka Sが中身からtypeを指定したように思われます。 Safariで再生できたのも、これが原因かと思われます。 対処法 例えば、macの場合は、以下によりmp4に変換できます。 brew install ffmpeg ffmpeg -i aaa.mov aaa.mp4 まとめ Omeka Sなどで動画ファイルを配信する際の参考になりましたら幸いです。

2024年7月4日 · 1 分 · Nakamura

Omeka SのSetEnv APPLICATION_ENVのproductionとdevelopmentの違い

Omeka Sでのエラー詳細の表示を有効にする手順は次の通りです。この設定を行うことで、「Omeka S has encountered an error」というページに具体的なエラーメッセージと詳細が表示されるようになります。また、PHPレベルのエラーや警告もページ上に表示されるようになります。これは開発中に問題の特定と解決を容易にするためのものですが、セキュリティ上の理由から本番環境では使用しないことが推奨されます。 エラー詳細の表示を有効にする手順 .htaccessファイルを見つける : Omeka Sのインストールフォルダのメインディレクトリに.htaccessファイルがあります。このファイルはWebサーバーの設定をカスタマイズするために使用されるものです。 .htaccessファイルを編集する : .htaccess ファイルをテキストエディタで開きます。 ファイル内の次の行を探します。 SetEnv APPLICATION_ENV "production" * この行を次のように変更します。 SetEnv APPLICATION_ENV "development" 変更を保存してサーバーを再起動する : 変更を保存した後、Webサーバーを再起動する必要がある場合があります。これはサーバーの設定に依存します。 この変更により、Omeka Sは「開発」モードで実行されるようになり、エラーが発生した際には詳細な情報が表示されるようになります。これは問題の診断と解決に非常に役立ちますが、セキュリティ上のリスクも伴うため、公開環境では使用しないようにしてください。

2024年7月4日 · 1 分 · Nakamura