Convert Parquet files to video and back using native PyAV encoding
Project description
videoparquet
Back up your Parquet files to YouTube. Up to 7x compression. ๐ฌ๐
Convert Parquet โ Video โ Upload to any video site โ Download โ Video โ Parquet. Your data survives!
pip install videoparquet
โ ๏ธ This is a novelty project! A fun experiment in using video platforms as data storage. Not for production use. Inspired by xarrayvideo1.
No external dependencies. Uses PyAV with bundled FFmpeg libraries. No
ffmpegbinary required.
Why?
Because you can upload videos anywhere. YouTube, Vimeo, Google Drive, iCloud, that random video hosting site from 2008 that's somehow still running.
Your data becomes a video. Videos are forever. QED. ๐
(Also: video codecs are surprisingly good at compressing structured numerical data.)
Benchmark
| Data Type | Compression | Notes |
|---|---|---|
| Smooth sensor grids | up to 7x | Low noise, high spatial correlation |
| Typical sensor data | 3-4x | Environmental monitoring, thermal grids |
| Random/noisy data | 2-3x | Still beats Parquet for floats |
| Integer/categorical | 0.5-1x | Parquet wins here, don't use videoparquet |
All roundtrips are lossless (max error < 0.001).
Best results with
- Continuous float data (not integers)
- Spatial grids (2D/3D sensor arrays)
- Temporal correlation between frames
- Low sensor noise
The Workflow
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ Parquet โ โโโถ โ Video โ โโโถ โ YouTube โ
โ (data) โ โ (.mkv) โ โ (backup!) โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ Download โ โโโถ โ Parquet โ
โ (.mkv) โ โ (restored!) โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
Quick Start
from videoparquet import parquet2video, video2parquet, infer_video_shape
import pandas as pd
import numpy as np
# Create some data
arr = np.random.randn(16, 64, 64, 3).astype(np.float32)
df = pd.DataFrame(arr.reshape(16, -1))
df.to_parquet('data.parquet')
# Auto-detect the video shape from your data
print(infer_video_shape(df)) # โ (16, 64, 64, 3)
# Define what to convert
conversion_rules = {
'myarray': (
list(df.columns), # columns to use
'auto', # auto-detect shape (or specify manually)
0, # PCA components (0 = none)
{'c:v': 'ffv1'}, # codec (ffv1 = lossless)
16, # bit depth
[arr.min(), arr.max()] # value range for normalization
)
}
# Convert Parquet โ Video
parquet2video('data.parquet', 'dataset_id', conversion_rules, output_path='./output')
# Creates: ./output/dataset_id/myarray.mkv (single file, all metadata embedded!)
# Convert Video โ Parquet (just pass the .mkv file directly)
video2parquet('./output/dataset_id/myarray.mkv')
# Creates: ./output/dataset_id/reconstructed_myarray.parquet
Format Options
Defaults: MKV container + FFV1 codec (lossless, recommended for local/cloud storage)
# Lossless (default)
params = {'c:v': 'ffv1'}
# Lossy H.264 for YouTube/sharing (smaller files)
params = {'c:v': 'libx264', 'format': 'mp4', 'crf': 18}
# Lossy H.265 (better compression, less compatible)
params = {'c:v': 'libx265', 'format': 'mp4', 'crf': 20}
# VP9 for WebM
params = {'c:v': 'libvpx-vp9', 'format': 'webm', 'crf': 20}
| Codec | Type | Container | Best For |
|---|---|---|---|
ffv1 |
Lossless | MKV | Local storage, exact roundtrip |
libx264 |
Lossy | MP4 | YouTube, sharing, preview |
libx265 |
Lossy | MP4 | Smaller files, modern players |
libvpx-vp9 |
Lossy | WebM | Web, open format |
โ ๏ธ YouTube note: YouTube re-encodes all uploads. Use MP4/H.264 for best compatibility. Metadata is preserved in the file but may be stripped by some platforms.
How It Works
- Reshape: Tabular data โ 4D array
(frames, height, width, channels) - Normalize: Scale values to 16-bit range, track min/max per channel
- Encode: Write as video using FFV1 codec (lossless, planar RGB)
- Decode: Read video, denormalize using embedded metadata
- Reconstruct: Reshape back to original DataFrame
All-in-one file: Metadata (shape, normalization params, column names) is embedded directly in the MKV container. No sidecar files needed - just upload/download the single .mkv file.
Installation
pip install videoparquet
Requirements:
- Python 3.8+
- NumPy, Pandas, PyArrow
- PyAV (bundled FFmpeg, no system install needed)
- scikit-learn (for optional PCA)
API Reference
parquet2video()
parquet2video(
parquet_path, # Path to input Parquet file
array_id, # Identifier (becomes subdirectory name)
conversion_rules, # Dict of {name: (columns, shape, pca, params, bits, range)}
output_path='./', # Output directory
compute_stats=False,# Print compression statistics
verbose=True, # Print progress
nan_fill=None, # Handle NaN: int, 'mean', 'min', 'max'
)
video2parquet()
video2parquet(
input_path, # Directory containing video files
array_id, # Dataset identifier
name='test', # Name of the array to reconstruct
)
Testing
pytest tests/ -v
Limitations
- Only 3-channel arrays supported (maps to RGB video planes)
- FFV1 lossless requires 16-bit planar format (
gbrp16le) - Data must be reshapeable to
(frames, height, width, 3)
License
MIT
Citation
If you use this in research, please cite the xarrayvideo paper:
@article{pellicer2025video,
title={Video compression for spatiotemporal Earth system data},
author={Pellicer-Valero, Oscar J and Aybar, Cesar and Camps-Valls, Gustau},
journal={arXiv preprint arXiv:2506.19656},
year={2025}
}
-
Pellicer-Valero, O. J., Aybar, C., & Camps-Valls, G. (2025). Video compression for spatiotemporal Earth system data. arXiv. https://doi.org/10.48550/arXiv.2506.19656 โฉ
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file videoparquet-0.2.0.tar.gz.
File metadata
- Download URL: videoparquet-0.2.0.tar.gz
- Upload date:
- Size: 31.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
adba98945bcbbd408b4c7767c57eb5d61f2aec2a1015ca6b1c42658ffbe6f50e
|
|
| MD5 |
1d8d72f2043edf913caf8e62934ae804
|
|
| BLAKE2b-256 |
6bbe82224206bf0e20b224be85f38559a0e64cab9d21a97448c097c230dd9e6c
|
Provenance
The following attestation bundles were made for videoparquet-0.2.0.tar.gz:
Publisher:
publish.yml on lmangani/videoparquet
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
videoparquet-0.2.0.tar.gz -
Subject digest:
adba98945bcbbd408b4c7767c57eb5d61f2aec2a1015ca6b1c42658ffbe6f50e - Sigstore transparency entry: 2064660977
- Sigstore integration time:
-
Permalink:
lmangani/videoparquet@c3d3eb3c8ed0f5ccdb2c33be3cbf5e05fefec9a7 -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/lmangani
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c3d3eb3c8ed0f5ccdb2c33be3cbf5e05fefec9a7 -
Trigger Event:
release
-
Statement type:
File details
Details for the file videoparquet-0.2.0-py3-none-any.whl.
File metadata
- Download URL: videoparquet-0.2.0-py3-none-any.whl
- Upload date:
- Size: 32.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
629abc8bdfe59670725e6a3e84de19055b5af151b7e946891a899c8c33a6f0bd
|
|
| MD5 |
bed79deffb5e4a939a80fd4fe55f5661
|
|
| BLAKE2b-256 |
b15ffda1c808239d514e2bfb2408fb57e29ea2e7ca49a07641ab0df07b3056eb
|
Provenance
The following attestation bundles were made for videoparquet-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on lmangani/videoparquet
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
videoparquet-0.2.0-py3-none-any.whl -
Subject digest:
629abc8bdfe59670725e6a3e84de19055b5af151b7e946891a899c8c33a6f0bd - Sigstore transparency entry: 2064661010
- Sigstore integration time:
-
Permalink:
lmangani/videoparquet@c3d3eb3c8ed0f5ccdb2c33be3cbf5e05fefec9a7 -
Branch / Tag:
refs/tags/0.2.0 - Owner: https://github.com/lmangani
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c3d3eb3c8ed0f5ccdb2c33be3cbf5e05fefec9a7 -
Trigger Event:
release
-
Statement type: