A low-dependency Python library for parsing and managing RIFF format files
Project description
riffy
A low-dependency Python library for parsing and managing RIFF (Resource Interchange File Format) files.
Riffy provides a pure Python implementation for working with RIFF format files, with initial support for WAV audio files. The library is designed to have zero external dependencies while providing robust parsing capabilities for managing RIFF chunks.
Features
- Zero Dependencies: Pure Python implementation with no external dependencies
- WAV File Support: Complete WAV file parsing with format validation
- RIFF Chunk Management: Access and inspect individual RIFF chunks
- Audio Metadata Extraction: Extract sample rate, channels, bit depth, and duration
- Format Validation: Automatic validation of file format and integrity
- Type Safety: Full type hints for better IDE support and code quality
- Lightweight: Minimal footprint, perfect for embedded systems or restricted environments
Installation
From PyPI
pip install riffy
From Source
# Clone the repository
git clone https://github.com/jmcmeen/riffy.git
cd riffy
# Install in development mode
pip install -e .
# Or build and install
pip install build
python -m build
pip install dist/riffy-*.whl
For Development
# Install with development dependencies
pip install -e ".[dev]"
Quick Start
Basic WAV File Parsing
from riffy import WAVParser
# Parse a WAV file
parser = WAVParser("audio.wav")
info = parser.parse()
# Access format information
print(f"Sample Rate: {info['format']['sample_rate']} Hz")
print(f"Channels: {info['format']['channels']}")
print(f"Bit Depth: {info['format']['bits_per_sample']} bits")
print(f"Duration: {info['duration_seconds']:.2f} seconds")
Accessing RIFF Chunks
from riffy import WAVParser
parser = WAVParser("audio.wav")
parser.parse()
# Access all chunks
for chunk_id, chunk in parser.chunks.items():
print(f"Chunk: {chunk_id}, Size: {chunk.size} bytes, Offset: {chunk.offset}")
# Access specific chunk
if 'fmt ' in parser.chunks:
fmt_chunk = parser.chunks['fmt ']
print(f"Format chunk size: {fmt_chunk.size}")
Working with Audio Data
from riffy import WAVParser
parser = WAVParser("audio.wav")
parser.parse()
# Access raw audio data
audio_data = parser.audio_data
print(f"Audio data size: {len(audio_data)} bytes")
# Get sample count
info = parser.get_info()
print(f"Total samples: {info['sample_count']}")
Getting Detailed File Information
from riffy import WAVParser
import json
parser = WAVParser("audio.wav")
info = parser.parse()
# Pretty print all information
print(json.dumps(info, indent=2))
Output example:
{
"file_path": "/path/to/audio.wav",
"file_size": 1234567,
"format": {
"audio_format": 1,
"channels": 2,
"sample_rate": 44100,
"byte_rate": 176400,
"block_align": 4,
"bits_per_sample": 16,
"is_pcm": true
},
"duration_seconds": 3.5,
"audio_data_size": 617400,
"sample_count": 154350,
"chunks": {
"fmt ": 16,
"data": 617400
}
}
API Reference
WAVParser
The main class for parsing WAV files.
Constructor
WAVParser(file_path: Union[str, Path])
Parameters:
file_path: Path to the WAV file (string orpathlib.Path)
Methods
parse() -> Dict
Parse the WAV file and return comprehensive information.
Returns: Dictionary containing file information, format details, and chunk data
Raises:
FileNotFoundError: If the file doesn't existInvalidWAVFormatError: If the file is not a valid WAV fileCorruptedFileError: If the file is corrupted or incomplete
get_info() -> Dict
Get comprehensive information about the parsed WAV file.
Returns: Dictionary with file metadata (must call parse() first)
Properties
format_info:WAVFormatobject containing format detailschunks: Dictionary ofWAVChunkobjects keyed by chunk IDaudio_data: Raw audio data as bytes
WAVFormat
Dataclass containing WAV format information.
Attributes:
audio_format: Audio format code (1 = PCM)channels: Number of audio channelssample_rate: Sample rate in Hzbyte_rate: Bytes per secondblock_align: Block alignment in bytesbits_per_sample: Bits per sample
Properties:
is_pcm: Boolean indicating if format is PCM (uncompressed)duration_seconds: Audio duration in seconds
WAVChunk
Dataclass representing a RIFF chunk.
Attributes:
id: Chunk identifier (e.g., "fmt ", "data")size: Chunk size in bytesdata: Raw chunk dataoffset: Byte offset in the file
Exception Hierarchy
RiffyError (base exception)
├── WAVError
│ ├── InvalidWAVFormatError
│ ├── CorruptedFileError
│ └── UnsupportedFormatError
└── ChunkError
├── InvalidChunkError
└── MissingChunkError
Exception Handling
from riffy import WAVParser, InvalidWAVFormatError, CorruptedFileError
try:
parser = WAVParser("audio.wav")
info = parser.parse()
except InvalidWAVFormatError as e:
print(f"Invalid WAV format: {e}")
except CorruptedFileError as e:
print(f"File is corrupted: {e}")
except FileNotFoundError:
print("File not found")
Supported Formats
Currently, Riffy supports:
- WAV Files: PCM (uncompressed) audio only
- RIFF Chunks: Standard chunk parsing for any RIFF file
Planned Support
- AVI files
- WebP images
- Additional WAV compression formats
- RIFF chunk writing/modification
Requirements
- Python 3.8 or higher
- No external dependencies!
Development
Running Tests
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run tests with coverage
pytest --cov=riffy --cov-report=html
Code Formatting
# Format code with black
black src/
# Lint with ruff
ruff check src/
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
Version 0.1.0 (Initial Release)
- Pure Python WAV file parser
- RIFF chunk management
- Zero external dependencies
- Full type hints
- Comprehensive error handling
Acknowledgments
- RIFF format specification: Microsoft RIFF Specification
- WAV format specification: WAV Audio File Format
Support
For bugs, feature requests, or questions, please open an issue.
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 riffy-0.1.0.tar.gz.
File metadata
- Download URL: riffy-0.1.0.tar.gz
- Upload date:
- Size: 8.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5630d1a5175ad2ee389045f69f269addccb4450e03589e73fd48d8b9b4d7e995
|
|
| MD5 |
bb12a56c421c9eb1b8e8b95b552848bd
|
|
| BLAKE2b-256 |
1c69e608f4337f9b91101fb22f6208328433ee08568da1c42b0e254da3ba73b4
|
File details
Details for the file riffy-0.1.0-py3-none-any.whl.
File metadata
- Download URL: riffy-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
481c707eccb1705252623fad3bcd342260c798d800bb52547f86282782d6c8af
|
|
| MD5 |
b40d45fe43c833e61149c810b1b81383
|
|
| BLAKE2b-256 |
afa4de11bc2c7f075419401ac411d995f0330de5b0b78d1ef4cf2540a82aa455
|