跳到内容

Blob 作为文件

与其他数据格式不同,大型多模态数据在 Lance 列式格式中是“一等公民”。Lance 提供高级 API 来在 Lance 数据集中存储和检索大型二进制对象(blob)。

Blob

Lance 使用 lance.BlobFile 提供大型二进制数据,这是一个类似文件的对象,可以惰性读取大型二进制对象。

要创建包含大型 blob 数据的 Lance 数据集,您可以通过将元数据 lance-encoding:blob 设置为 true,将大型二进制列标记为 blob 列。

import pyarrow as pa

schema = pa.schema(
    [
        pa.field("id", pa.int64()),
        pa.field("video",
            pa.large_binary(),
            metadata={"lance-encoding:blob": "true"}
        ),
    ]
)

要将 blob 数据写入 Lance 数据集,请使用 blob 模式创建 PyArrow 表,然后使用 lance.write_dataset

import lance

# First, download a sample video file for testing
# wget https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4
import urllib.request
urllib.request.urlretrieve(
    "https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4",
    "sample_video.mp4"
)

# Then read the video file content
with open("sample_video.mp4", 'rb') as f:
    video_data = f.read()

# Create table with blob data
table = pa.table({
    "id": [1],
    "video": [video_data],
}, schema=schema)

# Write to Lance dataset
ds = lance.write_dataset(
    table,
    "./youtube.lance",
    schema=schema
)

要从 Lance 数据集获取 blob,您可以使用 lance.dataset.LanceDataset.take_blobs

例如,使用 BlobFile 从视频文件中提取帧而无需将整个视频加载到内存中是很容易的。

import av # pip install av
import lance

ds = lance.dataset("./youtube.lance")
start_time, end_time = 500, 1000
# Get blob data from the first row (id=0)
blobs = ds.take_blobs("video", ids=[0])
with av.open(blobs[0]) as container:
    stream = container.streams.video[0]
    stream.codec_context.skip_frame = "NONKEY"

    start_time = start_time / stream.time_base
    start_time = start_time.as_integer_ratio()[0]
    end_time = end_time / stream.time_base
    container.seek(start_time, stream=stream)

    for frame in container.decode(stream):
        if frame.time > end_time:
            break
        display(frame.to_image())
        clear_output(wait=True)