media_source 0.2.0-alpha.3
media_source: ^0.2.0-alpha.3 copied to clipboard
Handle media from files, memory, or network with automatic type detection and cross-platform file operations.
Media Source
A Flutter package for handling different media sources with automatic type detection.
Motivation #
When building media-rich applications, you often need to handle media from multiple sources: files stored locally, data in memory (like camera captures or downloaded content), and URLs from remote servers. Managing these different states becomes complex when you need to:
Inspired by Flutterβs ImageProvider, which unifies images from assets, files, memory, and network under a single API, this library applies the same idea to general media. The goal is to let you swap sources freely without changing your business logic.
- Load a file from disk, process it in memory, then upload it
- Download media from a URL, cache it locally, and convert it between formats
- Handle user-selected files, camera captures, and network resources uniformly
- Switch between sources without rewriting your business logic
This package provides a unified, type-safe API to handle all these scenarios. Whether your media starts as a file, exists in memory, or comes from a network URL, you can work with it consistently and convert between states seamlessly.
Features #
- π― Type-safe media source abstraction - Handle files, memory, and network sources uniformly
- π Multiple source types -
FileMediaSource,MemoryMediaSource,NetworkMediaSource - π Automatic media type detection - From file paths, MIME types, and byte data
- π Cross-platform support - Works on Flutter mobile, web, and desktop
- π MIME type utilities - Comprehensive mapping of extensions to media types
- π§© Extension-based lookups - Quick checks with pre-built extension sets
- π Flexible conversions - Convert between different source types (e.g., file to memory)
- πΎ File operations - Move, copy, save, and delete operations for file-based media
- οΏ½ Built on
cross_file- Seamless cross-platform file handling - β 100% test coverage - Thoroughly tested and reliable
Getting started #
Add media_source to your pubspec.yaml:
dependencies:
media_source: ^0.2.0-alpha.3
Then run:
flutter pub get
π‘ Quick Start: Check out the complete example/main.dart file for a comprehensive demonstration of all features.
Usage #
Basic Media Type Detection #
import 'package:media_source/media_source.dart';
// Detect from file path
final imageType = MediaType.fromPath('/path/to/photo.jpg', 'image/jpeg');
print(imageType); // ImageType
// Detect from bytes
final bytes = await file.readAsBytes();
final videoType = MediaType.fromBytes(bytes, 'video/mp4');
print(videoType); // VideoType
Working with File Media Source #
import 'package:media_source/media_source.dart';
// Create from file path
final video = await VideoFileMedia.fromPath(
'/path/to/video.mp4',
duration: Duration(seconds: 120),
);
// Access properties
print(video.name); // video.mp4
print(video.size); // File size
print(video.metadata.duration); // Duration(seconds: 120)
// File operations
await video.saveTo('/backup/video.mp4');
await video.moveTo('/new/location/video.mp4');
final memoryMedia = await video.convertToMemory();
await video.delete();
// Create from XFile
final file = XFile('/path/to/audio.mp3');
final audio = await AudioFileMedia.fromFile(
file,
name: 'song.mp3',
duration: Duration(minutes: 3),
);
Working with Memory Media Source #
import 'package:media_source/media_source.dart';
import 'dart:typed_data';
// Create from byte data
final bytes = Uint8List.fromList([/* your data */]);
final image = ImageMemoryMedia(
bytes,
name: 'photo.jpg',
mimeType: 'image/jpeg',
);
// Access properties
print(image.bytes); // Uint8List
print(image.size); // Size in bytes
print(image.name); // photo.jpg
// Save to file system
final fileMedia = await image.saveToFolder('/images');
print(fileMedia.file.path); // /images/photo.jpg
// Convert to different types
final videoMemory = VideoMemoryMedia(
videoBytes,
name: 'clip.mp4',
duration: Duration(seconds: 10),
);
Working with Network Media Source #
import 'package:media_source/media_source.dart';
import 'package:sized_file/sized_file.dart';
// Create from URL with automatic type detection
final media = NetworkMediaSource.fromUrl(
'https://example.com/video.mp4',
mediaType: FileType.video,
size: 5.mb,
name: 'video.mp4',
);
// Create type-specific network media
final video = VideoNetworkMedia.url(
'https://example.com/movie.mp4',
name: 'movie.mp4',
size: 150.mb,
duration: Duration(minutes: 90),
);
final audio = AudioNetworkMedia(
Uri.parse('https://example.com/song.mp3'),
name: 'song.mp3',
size: 5.mb,
duration: Duration(minutes: 3, seconds: 45),
);
final image = ImageNetworkMedia.url(
'https://example.com/photo.jpg',
name: 'photo.jpg',
size: 2.mb,
);
// Access properties
print(video.uri); // Uri object
print(video.name); // movie.mp4
print(video.size); // 150 MB
print(video.metadata.duration); // Duration
Complete Example #
import 'package:media_source/media_source.dart';
import 'package:sized_file/sized_file.dart';
Future<void> processMedia() async {
// Create a video file media
final video = await VideoFileMedia.fromPath(
'/path/to/video.mp4',
duration: Duration(minutes: 2),
);
// Check media type and handle accordingly
final result = video.fold<String>(
file: (fileMedia) async {
// Save a backup
await fileMedia.saveTo('/backup/video.mp4');
// Convert to memory for processing
final memoryMedia = await fileMedia.convertToMemory();
// Process the bytes
print('Processing ${memoryMedia.bytes.length} bytes');
return 'File processed: ${fileMedia.name}';
},
memory: (memoryMedia) {
return 'Memory media: ${memoryMedia.size}';
},
network: (networkMedia) {
return 'Network media: ${networkMedia.uri}';
},
orElse: () => 'Unknown media type',
);
print(result);
}
Type-Specific Operations with Pattern Matching #
import 'package:media_source/media_source.dart';
// Pattern matching on MediaType
final mediaType = MediaType.fromPath('song.mp3', 'audio/mpeg');
final description = mediaType.fold(
audio: (audio) => 'Audio file with duration: ${audio.duration}',
video: (video) => 'Video file with duration: ${video.duration}',
image: (image) => 'Image file',
document: (doc) => 'Document file',
url: (url) => 'URL reference',
orElse: () => 'Other file type',
);
print(description);
// Pattern matching on MediaSource
final media = await VideoFileMedia.fromPath('/path/to/video.mp4');
final info = media.fold(
file: (f) => 'File: ${f.file.path}',
memory: (m) => 'Memory: ${m.size}',
network: (n) => 'URL: ${n.uri}',
orElse: () => 'Unknown source',
);
print(info); // File: /path/to/video.mp4
Extension Methods on XFile #
import 'package:media_source/media_source.dart';
import 'package:cross_file/cross_file.dart';
final file = XFile('/path/to/document.pdf');
// Get media type
print(file.mediaType); // DocumentType
// Get file name
print(file.name); // document.pdf
// Get size
final size = await file.size();
// Check existence
if (await file.exists()) {
// Delete if exists
await file.delete();
}
API Reference #
MediaType #
Base class for media type classification:
MediaType.image- Image filesMediaType.audio- Audio filesMediaType.video- Video filesMediaType.document- PDF documentsMediaType.url- URL referencesMediaType.other- Other file types
Subtypes:
ImageType- Image mediaAudioType- Audio media with optional durationVideoType- Video media with optional durationDocumentType- Document media (PDF)UrlType- URL referencesOtherType- Unclassified media
Methods:
MediaType.fromPath(String path, String? mimeType)- Create from file pathMediaType.fromBytes(Uint8List bytes, String? mimeType)- Create from byte datawhen<T>({...})- Pattern matching for type-specific operationsisAny(List<MediaType> list)- Check if type is in listisAnyType(List<Type> list)- Check if runtime type is in list
MediaSource Implementations #
FileMediaSource
FileMediaSource(XFile file)
MemoryMediaSource
MemoryMediaSource(
Uint8List bytes, {
String? mimeType,
String? name,
})
NetworkMediaSource
NetworkMediaSource(String url)
MIME Groups Utilities #
Maps:
extensionToMediaType- Map<String, MediaType>mediaTypeExtensions- Map<MediaType, Set
Sets:
imageExtensions- All image file extensionsaudioExtensions- All audio file extensionsvideoExtensions- All video file extensionsdocumentExtensions- All document file extensionsotherExtensions- All other file extensions
Functions:
MediaType mediaTypeForExtension(String extension)- Get MediaType for an extensionbool isExtensionOfType(String extension, MediaType type)- Check if extension matches type
Supported Media Types #
The package automatically detects and categorizes hundreds of file extensions including:
Images: jpg, jpeg, png, gif, bmp, webp, svg, ico, tiff, avif, heic, heif, and more
Audio: mp3, aac, wav, flac, ogg, m4a, wma, opus, and more
Video: mp4, mov, avi, mkv, webm, flv, wmv, m4v, 3gp, and more
Documents: pdf
Other: All other MIME types and extensions
Extensibility #
You can extend the package to fit custom domain needs:
- Create a new media type by extending
FileTypeImpl(seelib/src/media_type.dart). - Create a new media source by extending
MediaSource<M extends FileType>or by implementing the conversion mixins (ToFileConvertableMedia,ToMemoryConvertableMedia).
Example β custom type and source:
import 'dart:typed_data';
import 'package:cross_file/cross_file.dart';
import 'package:media_source/media_source.dart';
class StickerType extends FileTypeImpl {
StickerType() : super.copy(FileType.other);
@override
List<Object?> get props => const [];
}
class StickerMemoryMedia extends MemoryMediaSource<StickerType> {
StickerMemoryMedia(Uint8List bytes, {required String name})
: super._(bytes, name: name, metadata: StickerType());
@override
Future<FileMediaSource<StickerType>> saveToFile(String path) async {
final file = XFile.fromData(bytes, name: name, path: path);
await PlatformUtils.instance.createDirectoryIfNotExists(path);
await file.saveTo(path);
// Return your own FileMediaSource<StickerType> implementation here
throw UnimplementedError();
}
}
Platform Support #
- β Android
- β iOS
- β Web
- β macOS
- β Windows
- β Linux
Additional information #
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
Issues #
If you encounter any issues or have suggestions, please file them in the issue tracker.
License #
This project is licensed under the MIT License - see the LICENSE file for details.
Author #
Hossam Eldin - GitHub
Acknowledgments #
- Uses cross_file for cross-platform file handling
- Built with file_type_plus for file type detection
- Size handling powered by sized_file