@bernierllc/content-type-video
v1.2.0
Published
Base video content type with file upload, local storage, and streaming URL generation
Readme
@bernierllc/content-type-video
Base video content type with file upload, local storage, and streaming URL generation for the BernierLLC Content Management Suite.
Installation
npm install @bernierllc/content-type-videoFeatures
- ✅ Video File Upload - Upload video files with validation (format, size)
- ✅ Local File Storage - Store videos in local file system with automatic directory creation
- ✅ Metadata Extraction - Extract video metadata (duration, dimensions, fps, codec)
- ✅ Streaming URL Generation - Generate streaming URLs for uploaded videos
- ✅ Configurable - Environment variables and constructor options
- ✅ TypeScript - Full type safety with strict mode
- ✅ Well Tested - 100% statements, functions, and lines coverage
Usage
Basic Usage
import { VideoContentType } from '@bernierllc/content-type-video';
// Create instance with defaults
const videoType = new VideoContentType();
// Upload a video file
const result = await videoType.upload(
videoBuffer, // Buffer or file path
'my-video.mp4',
'user-123' // Optional: uploaded by
);
if (result.success) {
console.log('Video uploaded!');
console.log('File path:', result.data?.filePath);
console.log('Streaming URL:', result.data?.streamingUrl);
console.log('Metadata:', result.data?.metadata);
}Custom Configuration
const videoType = new VideoContentType({
baseType: 'video',
editor: 'file-upload-with-player',
storage: 'file',
publishing: 'streaming-url',
uploadOptions: {
maxSizeBytes: 1024 * 1024 * 1024, // 1GB
allowedFormats: ['mp4', 'webm'],
generateThumbnail: true,
extractMetadata: true,
storageBasePath: './custom-storage/videos'
},
streamingBaseUrl: '/cdn/video/stream'
});Environment Variables
VIDEO_MAX_SIZE_BYTES=524288000 # Maximum file size (500MB default)
VIDEO_ALLOWED_FORMATS=mp4,webm,mov,avi # Comma-separated allowed formats
VIDEO_GENERATE_THUMBNAIL=true # Generate thumbnail on upload
VIDEO_EXTRACT_METADATA=true # Extract metadata on upload
VIDEO_STORAGE_BASE_PATH=./storage/videos # Base path for video file storage
VIDEO_STREAMING_BASE_URL=/api/video/stream # Base URL for streaming endpointAPI Reference
VideoContentType
Main class for video content type operations.
Constructor
constructor(config?: Partial<VideoContentTypeConfig>)Methods
upload(file, filename, uploadedBy?)
Upload a video file and extract metadata.
async upload(
file: Buffer | string,
filename: string,
uploadedBy?: string
): Promise<VideoContentResult<VideoContentData>>Parameters:
file: Buffer or file path to the video filefilename: Original filename (used for extension detection)uploadedBy: Optional user identifier who uploaded the video
Returns: Result object with uploaded video data or error
validate(file, filename)
Validate video file before upload.
async validate(
file: Buffer | string,
filename: string
): Promise<VideoContentResult<void>>get(localPath)
Retrieve video file from storage.
async get(localPath: string): Promise<Buffer | null>delete(localPath)
Delete video file from storage.
async delete(localPath: string): Promise<boolean>exists(localPath)
Check if video file exists in storage.
async exists(localPath: string): Promise<boolean>getStreamingUrl(localPath)
Generate streaming URL for video file.
getStreamingUrl(localPath: string): stringvalidateContent(data)
Validate video content data structure.
validateContent(data: VideoContentData): VideoContentResult<VideoContentData>register()
Register video content type with content type registry.
async register(): Promise<void>Type Definitions
VideoMetadata
interface VideoMetadata {
filename: string;
mimeType: string; // e.g., 'video/mp4'
size: number; // File size in bytes
duration: number; // Duration in seconds
width: number; // Video width in pixels
height: number; // Video height in pixels
fps: number; // Frames per second
thumbnail?: string; // Optional thumbnail URL
bitrate?: number; // Optional bitrate
codec?: string; // Optional codec information
}VideoContentData
interface VideoContentData {
filePath: string; // Local file path
streamingUrl: string; // Generated streaming URL
metadata: VideoMetadata; // Video metadata
uploadedAt: Date; // Upload timestamp
uploadedBy?: string; // Optional uploader identifier
}VideoUploadOptions
interface VideoUploadOptions {
maxSizeBytes?: number; // Default: 500MB
allowedFormats?: string[]; // Default: ['mp4', 'webm', 'mov', 'avi']
generateThumbnail?: boolean; // Default: true
extractMetadata?: boolean; // Default: true
storageBasePath?: string; // Default: './storage/videos'
}Examples
Upload from Buffer
import fs from 'fs';
import { VideoContentType } from '@bernierllc/content-type-video';
const videoType = new VideoContentType();
const videoBuffer = fs.readFileSync('./my-video.mp4');
const result = await videoType.upload(videoBuffer, 'my-video.mp4');
if (result.success) {
console.log('Upload successful!');
console.log(`Streaming URL: ${result.data?.streamingUrl}`);
console.log(`Duration: ${result.data?.metadata.duration}s`);
console.log(`Resolution: ${result.data?.metadata.width}x${result.data?.metadata.height}`);
}Upload from File Path
const result = await videoType.upload('/path/to/video.mp4', 'video.mp4', 'user-123');Validate Video Format
const result = await videoType.upload(buffer, 'video.avi');
if (!result.success) {
console.error('Upload failed:', result.error);
// Error: File format avi not allowed. Allowed: mp4, webm, mov, avi
}Custom Storage Location
const videoType = new VideoContentType({
uploadOptions: {
storageBasePath: '/data/videos'
}
});Delete Uploaded Video
const uploadResult = await videoType.upload(buffer, 'video.mp4');
if (uploadResult.success && uploadResult.data) {
const filePath = uploadResult.data.filePath;
// Later, delete the video
const deleted = await videoType.delete(filePath);
if (deleted) {
console.log('Video deleted successfully');
}
}Integration
Logger Integration
- Status: planned
- Usage: Log upload operations, metadata extraction, and errors
NeverHub Integration
- Status: optional
- Events Published:
video.uploaded- When video file is successfully uploadedvideo.metadata-extracted- When metadata extraction completesvideo.validation-failed- When video validation fails
Docs-Suite Compatibility
- Status: ready
- Format: typedoc
- Documentation: Complete API documentation with TypeScript types
Platform-Specific Extensions
This base package is designed to be extended for platform-specific video content types:
@bernierllc/content-type-youtube- YouTube video integration@bernierllc/content-type-tiktok- TikTok video integration@bernierllc/content-type-instagram-reels- Instagram Reels integration
Dependencies
@bernierllc/content-type-registry(^1.0.3) - Content type registrationzod(^3.22.0) - Schema validation
Development
# Install dependencies
npm install
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Build package
npm run build
# Lint code
npm run lintQuality Metrics
- Test Coverage: 98.86% statements, 100% functions, 98.86% lines, 79.31% branches
- Tests: 37 passing, 0 failing (100% pass rate)
- TypeScript: Strict mode enabled, zero errors
- Linting: Zero errors or warnings
- Build: Successful compilation
License
Copyright (c) 2025 Bernier LLC
This file is licensed to the client under a limited-use license. The client may use and modify this code only within the scope of the project it was delivered for. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
Related Packages
- @bernierllc/content-type-registry - Content type registration and base interfaces
- @bernierllc/content-management-suite - Complete content management system
Part of Suite
- @bernierllc/content-management-suite - Comprehensive content management solution
Contributing
This package is part of the BernierLLC monorepo and follows strict quality standards:
- 90%+ test coverage (all metrics)
- 100% test pass rate
- TypeScript strict mode
- Zero linting errors
- License headers in all files
For more information, see CLAUDE.md in the repository root.
