txex
v0.0.4
Published
Extract files from BSV transactions (B://, BCAT, Ordinals)
Maintainers
Readme
txex
Extract, cache, and transform media from the blockchain.

Installation
npm install -g txexTable of Contents
Features
- Universal Extraction - Seamlessly handles B://, BCAT, 1Sat Ordinals, and ORDFS Streams
- Media Processing - Resize, crop, format conversion for images (sharp), video, and audio (ffmpeg)
- Collection Downloads - Auto-detect and download entire NFT collections in parallel
- Origin Tracking - Automatically traces marketplace listings back to their inscription
- Smart Caching - Two-tier cache for raw transactions and transformed outputs
- TypeScript Ready - Use as CLI or import as a fully-typed library
CLI Usage
Basic Extraction
# Extract from outpoint (txid_vout)
txex <outpoint> -o output.mp4
# Auto-detect filename and extension
txex abc123...def456_0
# Parallel chunk fetches for large files
txex abc123...def456_0 -c 10Collections

# Download entire collection (auto-detected)
txex <collection_outpoint>
# Limit number of items
txex <collection_outpoint> --limit 50
# Custom output directory
txex <collection_outpoint> -o ./my-collectionImage Transforms

# Resize to width, convert to WebP
txex <outpoint> -w 800 -f webp -o thumb.webp
# Generate blurred placeholder
txex <outpoint> -w 50 --blur 10 -f webp -q 50
# Social media card (Cover fit, specific dimensions)
txex <outpoint> -w 1200 -h 630 --fit cover -f webp -o og.webpTransform Options
| Option | Short | Description |
|--------|-------|-------------|
| --width <px> | -w | Resize width |
| --height <px> | -h | Resize height |
| --format <fmt> | -f | Output format: webp, avif, png, jpg (SVGs auto-convert to PNG) |
| --fit <mode> | | Resize fit: cover, contain, fill, inside |
| --position <pos> | | Crop position: center, top, bottom, left, right, entropy, attention |
| --quality <n> | -q | Output quality 1-100 (default: 80) |
| --blur <radius> | | Blur radius 0.3-1000 |
| --grayscale | | Convert to grayscale |
| --rotate <deg> | | Rotate degrees |
| --flip | | Flip vertically |
| --flop | | Flip horizontally |
Video Transforms
Requires ffmpeg installed.
# Extract thumbnail at 5 seconds
txex <outpoint> --thumbnail 5 -w 320 -o thumb.jpg
# Convert to WebM, resize, trim to 10 seconds
txex <outpoint> -w 720 -f webm --duration 10 -o clip.webm
# Extract GIF preview (first 3 seconds, 10fps)
txex <outpoint> -w 480 -f gif --duration 3 --fps 10 -o preview.gif
# Strip audio
txex <outpoint> -f mp4 --no-audio -o silent.mp4Video Options
| Option | Description |
|--------|-------------|
| --thumbnail <time> | Extract frame at timestamp (e.g., 5 or 00:00:05) |
| --thumbnail-format | Thumbnail format: jpg, png, webp (default: jpg) |
| --start <time> | Trim start time |
| --duration <time> | Trim duration |
| --fps <n> | Output frames per second |
| --no-audio | Strip audio track |
| -f <fmt> | Output format: mp4, webm, gif, mov |
Audio Transforms
Requires ffmpeg installed.
# Convert to different format
txex <outpoint> -f ogg -o track.ogg
# High quality MP3 with bitrate
txex <outpoint> -f mp3 --bitrate 320k -o track.mp3
# Trim audio (start at 10s, 30s duration)
txex <outpoint> --start 10 --duration 30 -f mp3 -o clip.mp3
# Normalize volume and convert to mono
txex <outpoint> --normalize --channels 1 -f wav -o normalized.wavAudio Options
| Option | Description |
|--------|-------------|
| -f <fmt> | Output format: mp3, wav, ogg, flac, aac, m4a |
| --bitrate <rate> | Bitrate (e.g., 128k, 320k) |
| --sample-rate <hz> | Sample rate (e.g., 44100, 48000) |
| --channels <n> | Channels: 1 (mono), 2 (stereo) |
| --start <time> | Trim start time |
| --duration <time> | Trim duration |
| --normalize | Normalize volume level |
Metadata Inspection
# Show metadata without extracting
txex info <outpoint>
# JSON output for scripting
txex info <outpoint> --jsonOutput includes: protocol, media type, size, filename, chunk count, origin (if different), and satoshis.
Color Extraction
# Extract dominant color, palette, and BlurHash
txex color <outpoint>
# Custom palette size
txex color <outpoint> -n 8
# Skip BlurHash generation
txex color <outpoint> --no-blurhash
# JSON output
txex color <outpoint> --jsonReturns dominant color, color palette, and BlurHash for images (useful for UI theming, placeholders, LQIP).
Cache Management
txex cache --stats # Show cache statistics
txex cache --clear # Clear all cached dataLibrary Usage
txex is fully typed. Install it locally:
npm install txeximport { extract, extractData, transformImage } from "txex";
// Get full file info
const file = await extract("abc123...def456_0");
console.log(file.protocol); // "bcat" | "b" | "ord" | "stream"
console.log(file.mediaType); // "video/mp4"
console.log(file.data); // Uint8Array
console.log(file.chunks); // Number of chunks (for BCAT/stream)
// Get raw data only
const data = await extractData("abc123...def456_0");
// Transform an image
const transformed = await transformImage(data, {
width: 800,
format: "webp",
quality: 85,
});Ordinal Chain Tracking
import { findOrigin, getNextOrdinalOutpoint, streamContent } from "txex";
// Find the origin inscription of a listing/transfer
const origin = await findOrigin({ txid: "abc123...", vout: 0 });
// Get next outpoint in chain (follows spends)
const next = await getNextOrdinalOutpoint({ txid: "abc123...", vout: 0 });
// Stream content chunks (async generator)
for await (const chunk of streamContent({ txid: "abc123...", vout: 0 })) {
console.log(chunk.mediaType, chunk.data.length);
}Custom Storage
By default, txex uses the filesystem for caching (~/.txex/cache/). For serverless/edge environments, you can provide a custom storage backend:
import { setStorageProvider, extract } from "txex";
// In-memory storage (for testing or ephemeral use)
import { MemoryStorage } from "txex";
setStorageProvider(new MemoryStorage());
// Custom storage (Redis, S3, Cloudflare KV, etc.)
setStorageProvider({
async get(key) {
const data = await redis.getBuffer(key);
return data ? new Uint8Array(data) : null;
},
async set(key, data) {
await redis.set(key, Buffer.from(data));
},
async delete(key) {
await redis.del(key);
},
// Optional methods for stats/cleanup
async list(prefix) { /* ... */ },
async clear(prefix) { /* ... */ },
});
// Now extract uses your storage
const file = await extract("abc123_0");StorageProvider Interface
interface StorageProvider {
get(key: string): Promise<Uint8Array | null>;
set(key: string, data: Uint8Array): Promise<void>;
delete(key: string): Promise<void>;
has?(key: string): Promise<boolean>; // optional
list?(prefix: string): Promise<string[]>; // optional
clear?(prefix?: string): Promise<void>; // optional
}Keys are prefixed with tx: for raw transactions and tfm: for transformed outputs.
Configuration
Create .txexrc or txex.config.json in your project or home directory:
{
"concurrency": 10,
"transform": {
"format": "webp",
"quality": 85
}
}Caching
txex uses a two-tier caching system:
- Transaction cache: Raw tx data stored in
~/.txex/cache/tx/ - Transform cache: Processed images stored in
~/.txex/cache/transformed/
txex abc123_0 -w 800 -f webp # First run: ~2.5s (network fetch)
txex abc123_0 -w 800 -f webp # Cached: ~0.05s
txex abc123_0 -w 400 -f png # Different transform: ~0.3s (tx cached)Supported Protocols
| Protocol | Prefix | Description |
|----------|--------|-------------|
| B:// | 19HxigV4QyBv3tHpQVcUEQyq1pzZVdoAut | Single transaction files |
| BCAT | 15DHFxWZJT58f9nhyGnsRBqrgwK4W6h4Up | Chunked files (large media) |
| Ordinals | OP_FALSE OP_IF "ord"... | 1Sat inscriptions |
| ORDFS Stream | ordfs/stream content type | Streaming across ordinal transfers |
Data Providers
txex uses JungleBus for transaction data. No API key required.
Collection metadata is fetched from GorillaPool's Ordinals API.
License
MIT
