# 動画データセットを作成する

このガイドでは、`VideoFolder`と一部のメタデータを使用して動画データセットを作成する方法を示します。これは、数千本の動画からなる動画データセットを素早く作成するためのノーコードソリューションです。

> [!TIP]
> ユーザーが連絡先情報を共有することを条件に、データセットへのアクセスを制御できます。この機能をHubで有効にする方法の詳細については、[Gated datasets](https://huggingface.co/docs/hub/datasets-gated)ガイドを参照してください。

## VideoFolder

`VideoFolder`は、コードを書かずに数千本の動画からなる動画データセットを素早く読み込むために設計されたデータセットビルダーです。

> [!TIP]
> 💡 `VideoFolder`がデータセットリポジトリの構造に基づいてデータセットの分割を作成する方法について詳しく知るには、[Split pattern hierarchy](repository_structure#split-pattern-hierarchy)をご覧ください。

`VideoFolder` は、ディレクトリ名に基づいてデータセットのクラスラベルを自動的に推論します。データセットは、次のようなディレクトリ構造で保存してください。

```
folder/train/dog/golden_retriever.mp4
folder/train/dog/german_shepherd.mp4
folder/train/dog/chihuahua.mp4

folder/train/cat/maine_coon.mp4
folder/train/cat/bengal.mp4
folder/train/cat/birman.mp4
```

データセットが`VideoFolder`の構造に従っている場合、[load_dataset()](/docs/datasets/main/ja/package_reference/loading_methods#datasets.load_dataset)で直接読み込むことができます:

```py
>>> from datasets import load_dataset

>>> dataset = load_dataset("path/to/folder")
```

これは、[load_dataset()](/docs/datasets/main/ja/package_reference/loading_methods#datasets.load_dataset) に `videofolder` を手動で渡し、`data_dir` にディレクトリを指定することと同等です。

```py
>>> dataset = load_dataset("videofolder", data_dir="/path/to/folder")
```

`videofolder` を使用して、複数のスプリットを含むデータセットを読み込むこともできます。そのためには、データセットのディレクトリが以下の構造になっている必要があります。

```
folder/train/dog/golden_retriever.mp4
folder/train/cat/maine_coon.mp4
folder/test/dog/german_shepherd.mp4
folder/test/cat/bengal.mp4
```

> [!WARNING]
> すべての動画ファイルが単一のディレクトリに格納されている場合、または同じディレクトリ階層にない場合、`label`列は自動的に追加されません。必要に応じて、`drop_labels=False`を明示的に設定してください。

データセットに関する追加情報（テキストキャプションやバウンディングボックスなど）を含める場合は、フォルダ内に`metadata.csv`ファイルとして追加してください。これにより、テキストキャプション付けや物体検出などの異なるコンピュータビジョンタスク用のデータセットを素早く作成できます。JSONLファイル`metadata.jsonl`またはParquetファイル`metadata.parquet`を使用することもできます。

```
folder/train/metadata.csv
folder/train/0001.mp4
folder/train/0002.mp4
folder/train/0003.mp4
```

`metadata.csv`ファイルには、動画ファイルとそのメタデータを関連付ける`file_name`または`*_file_name`フィールドが必要です。

```csv
file_name,additional_feature
0001.mp4,This is a first value of a text feature you added to your videos
0002.mp4,This is a second value of a text feature you added to your videos
0003.mp4,This is a third value of a text feature you added to your videos
```

または`metadata.jsonl`を使用します:

```jsonl
{"file_name": "0001.mp4", "additional_feature": "This is a first value of a text feature you added to your videos"}
{"file_name": "0002.mp4", "additional_feature": "This is a second value of a text feature you added to your videos"}
{"file_name": "0003.mp4", "additional_feature": "This is a third value of a text feature you added to your videos"}
```

ここでは、`file_name`はメタデータファイルの隣にある動画ファイルの名前である必要があります。より一般的には、メタデータを含むディレクトリから動画ファイルまでの相対パスである必要があります。

データセットの各行で複数の動画に参照させることができます。例えば、入力と出力の両方が動画の場合です。

```jsonl
{"input_file_name": "0001.mp4", "output_file_name": "0001_output.mp4"}
{"input_file_name": "0002.mp4", "output_file_name": "0002_output.mp4"}
{"input_file_name": "0003.mp4", "output_file_name": "0003_output.mp4"}
```

動画のリストを定義することもできます。その場合、フィールド名を`file_names`または`*_file_names`にする必要があります。以下に例を示します。

```jsonl
{"videos_file_names": ["0001_left.mp4", "0001_right.mp4"], "label": "moving_up"}
{"videos_file_names": ["0002_left.mp4", "0002_right.mp4"], "label": "moving_down"}
{"videos_file_names": ["0003_left.mp4", "0003_right.mp4"], "label": "moving_right"}
```

### 動画キャプショニング

Videoキャプショニングのデータセットには、動画の説明となるテキストが含まれます。`metadata.csv`の例は以下のようになります。

```csv
file_name,text
0001.mp4,This is a golden retriever playing with a ball
0002.mp4,A german shepherd
0003.mp4,One chihuahua
```

`VideoFolder`でデータセットを読み込むと、動画キャプション用の`text`列が作成されます:

```py
>>> dataset = load_dataset("videofolder", data_dir="/path/to/folder", split="train")
>>> dataset[0]["text"]
"This is a golden retriever playing with a ball"
```

### Hubにデータセットをアップロード

データセットを作成した後、`huggingface_hub` などを使用して共有できます。[huggingface_hub](https://huggingface.co/docs/huggingface_hub/index) ライブラリがインストールされていること、および Hugging Face アカウントにログインしていることを確認してください（詳細は [Upload with Python tutorial](upload_dataset#upload-with-python) を参照）。

`huggingface_hub.HfApi.upload_folder` を使用して、データセットをアップロードします:

```py
from huggingface_hub import HfApi
api = HfApi()

api.upload_folder(
    folder_path="/path/to/local/dataset",
    repo_id="username/my-cool-dataset",
    repo_type="dataset",
)
```

## WebDataset

[WebDataset](https://github.com/webdataset/webdataset)形式はTARアーカイブをベースとしており、大規模な動画データセットに適しています。実際、動画をTARアーカイブにグループ化して（例えば、1つのTARアーカイブあたり1GBの動画）、数千個のTARアーカイブを持つことができます：

```
folder/train/00000.tar
folder/train/00001.tar
folder/train/00002.tar
...
```

アーカイブでは、各サンプルは同じプレフィックスを持つファイルで構成されています:

```
e39871fd9fd74f55.mp4
e39871fd9fd74f55.json
f18b91585c4d3f3e.mp4
f18b91585c4d3f3e.json
ede6e66b2fb59aab.mp4
ede6e66b2fb59aab.json
ed600d57fcee4f94.mp4
ed600d57fcee4f94.json
...
```

JSONファイルやテキストファイルなどを使用して、動画のラベル/キャプション/特徴量を指定できます。

WebDataset形式とPythonライブラリに関する詳細については、[WebDatasetのドキュメント](https://webdataset.github.io/webdataset)を参照してください。

WebDatasetを読み込むと、ファイルの拡張子ごとに1列ずつ作成されます（ここではmp4とjson）：

```python
>>> from datasets import load_dataset

>>> dataset = load_dataset("webdataset", data_dir="/path/to/folder", split="train")
>>> dataset[0]["json"]
{"bbox": [[302.0, 109.0, 73.0, 52.0]], "categories": [0]}
```

## Lance

[Lance](https://lance.org)は、オープンなマルチモーダルなレイクハウス用テーブル形式です。Lanceテーブルでは、テキストやスカラー値だけでなく、画像、音声、動画などの大きなバイナリオブジェクト（blob）も、タブラーデータと並んでネイティブに保存できます。

Lanceには、Lanceデータセット内で大きなblobを保存・取得することを容易にする[blob API](https://lance.org/guide/blob/)が提供されています。以下の例では、より重い動画blobを読み込まずにメタデータを効率的にブラウジングし、その後、必要な動画blobをオンデマンドで取得する方法を示しています。

動画を保存する Lance テーブルの代表的な例を以下に示します（`video_blob` 列は Lance の blob エンコーディングを使用しています）：

```text
+------------------------------------------+-----------------+-----+------------------------------------------+
| caption                                  | aesthetic_score | ... | video_blob                               |
+------------------------------------------+-----------------+-----+------------------------------------------+
| "a breathtaking view of a mounta..."     | 5.2401          | ... | {position: 0, size: 4873879}             |
| "a captivating view of the sun, b..."    | 5.2401          | ... | {position: 4873920, size: 3370571}       |
+------------------------------------------+-----------------+-----+------------------------------------------+
```

### 生の動画ファイルからLanceデータセットを書き出す

ディスク上の生動画ファイルと関連するメタデータ（キャプションやスコアなど）から、ローカルの`*.lance`ディレクトリに自己完結型のLanceデータセットを書き出すことができます（Lanceデータセットはディスク上のディレクトリであり、`.lance`サフィックスで命名するのが一般的です）：

```py
import lance
import pyarrow as pa

import urllib.request

schema = pa.schema(
    [
        pa.field("caption", pa.utf8()),
        pa.field("aesthetic_score", pa.float64()),
        pa.field(
            "video_blob",
            pa.large_binary(),
            metadata={"lance-encoding:blob": "true"},
        ),
    ]
)

# Provide video files alongside metadata
rows = [
    {
        "video_path": "/path/to/videos/0001.mp4",
        "caption": "a breathtaking view of a mountainous landscape ...",
        "aesthetic_score": 5.240138053894043,
    },
    {
        "video_path": "0002.mp4",
        "caption": "a captivating view of the sun, bathed in hues ...",
        "aesthetic_score": 5.240137100219727,
    },
]

video_bytes = []
for r in rows:
    with open(r["video_path"], "rb") as f:
        video_bytes.append(f.read())

table = pa.table(
    {
        "caption": [r["caption"] for r in rows],
        "aesthetic_score": [r["aesthetic_score"] for r in rows],
        "video_blob": video_bytes,
    },
    schema=schema,
)

ds = lance.write_dataset(
    table,
    "./videos.lance",
    schema=schema,
    mode="create",
)
```

メタデータと動画バイトを`videos.lance/`内にまとめて保存するため、`*.mp4`ファイルを個別に同期させることなく、単一のディレクトリを移動またはコピーできます。

Lanceテーブルが動画を保存している場合の代表的なビューは以下のようになります（`video_blob`カラムには、Lanceデータセット内でネイティブにblobとして保存されるデータが含まれています）：

```text
+------------------------------------------+-----------------+-----+------------------------------------------+
| caption                                  | aesthetic_score | ... | video_blob                               |
+------------------------------------------+-----------------+-----+------------------------------------------+
| "a breathtaking view of a mounta..."     | 5.2401          | ... | {position: 0, size: 4873879}             |
| "a captivating view of the sun, b..."    | 5.2401          | ... | {position: 4873920, size: 3370571}       |
+------------------------------------------+-----------------+-----+------------------------------------------+
```

生成された`videos.lance/`ディレクトリをHubにアップロードし（`huggingface_hub.HfApi.upload_folder`などを使用）、メタデータと動画を単一の成果物としてまとめて保持したまま、データセットリポジトリとして共有できます。

> [!TIP]
> Lance データセットは、データがディスク上にカラムナフォーマットで保存されるため、非常に大きなサイズ（テラバイト以上）までスケーリングできます。Lance における大規模なブロブの保存と取得に関するベストプラクティスの最新情報については、[blob API](https://lance.org/guide/blob/) ガイドを参照してください。

大規模なデータセットを書き込む場合、各`*.lance`ファイルのサイズを数GB程度に制限するのが一般的に推奨されます。イテレータでデータを収集し、データセットを書き込む際に`max_bytes_per_file`パラメータを指定するだけです:

```python
MAX_BYTES_PER_FILE = 5 * 1024 * 1024 * 1024  # ~5 GB per file

# Write as Lance dataset with file size limits for each *.lance file
ds = lance.write_dataset(
    table,
    "./videos.lance",
    schema=schema,
    mode="create",
    max_bytes_per_file=MAX_BYTES_PER_FILE,
)
```

Lanceデータセットの取り扱いに関する詳細については、[Lanceのドキュメント](https://lance.org)を参照してください。

