TSS Video Glimpse 🎬
A powerful, elegant, and highly efficient cross-platform Flutter package for generating stunning video previews and thumbnails from multiple sources. Built with TSS (Thumbnail Snapshot Service) technology, this package provides seamless integration with network URLs, local assets, and Firebase Storage paths.
🌟 Why TSS Video Glimpse?
TSS Video Glimpse stands out from other video preview packages with its:
- 🚀 Lightning-fast performance with intelligent caching
- 🎨 Beautiful, customizable UI components
- 🌐 True cross-platform support (Android, iOS, Web, Linux, macOS, Windows)
- 🔥 Firebase Storage integration out of the box
- 📦 Smart memory management to prevent leaks
- 🎯 Simple, intuitive API that just works
- 🛡️ Production-ready with comprehensive error handling
✨ Features
📹 Multi-Source Support
- Network URLs (HTTP/HTTPS) - Stream from any web source
- Local Assets - Bundle videos with your app
- Firebase Storage - Direct integration with Firebase Storage paths
- YouTube - Play YouTube videos directly via URL
🎯 Cross-Platform Excellence
- ✅ Android (API 21+)
- ✅ iOS (iOS 12+)
- ✅ Web (All modern browsers)
- ✅ Linux
- ✅ macOS
- ✅ Windows
🚀 Performance Features
- Smart Caching - Automatic caching for network videos
- Memory Optimization - Efficient memory management
- Lazy Loading - Load previews only when needed
- Configurable Cache Duration - Control cache lifetime
🎨 Customization Options
- Custom placeholder widgets
- Custom error handling widgets
- Loading indicators
- Aspect ratio control
- Quality settings (Low, Medium, High)
- BoxFit options for perfect layouts
📦 Installation
Add this to your package's pubspec.yaml file:
dependencies:
tss_video_glimpse: ^0.1.5
Then run:
flutter pub get
🚀 Quick Start
Basic Usage
The simplest way to display a video preview:
import 'package:tss_video_glimpse/tss_video_glimpse.dart';
// Network URL
TssVideoGlimpse(
videoUrl: 'https://example.com/video.mp4',
width: 200,
height: 150,
)
Asset Video
Display a preview from a local asset:
TssVideoGlimpse.asset(
assetPath: 'assets/videos/sample.mp4',
width: 200,
height: 150,
)
Firebase Storage
Load video directly from Firebase Storage:
TssVideoGlimpse.firebase(
firebasePath: 'videos/sample.mp4',
width: 200,
height: 150,
)
YouTube Video
Display a YouTube video preview and player:
TssVideoGlimpse(
youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
width: 200,
height: 150,
)
📚 Detailed Usage Examples
Example 1: Network Video with Custom Styling
TssVideoGlimpse(
videoUrl: 'https://example.com/video.mp4',
width: 300,
height: 200,
fit: BoxFit.cover,
quality: TssVideoQuality.high,
placeholder: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue.shade300, Colors.purple.shade300],
),
borderRadius: BorderRadius.circular(12),
),
child: const Center(
child: CircularProgressIndicator(color: Colors.white),
),
),
errorWidget: Container(
decoration: BoxDecoration(
color: Colors.red.shade50,
borderRadius: BorderRadius.circular(12),
),
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.error_outline, size: 48, color: Colors.red),
SizedBox(height: 8),
Text('Failed to load video', style: TextStyle(color: Colors.red)),
],
),
),
onError: (error) {
print('Video loading error: $error');
// Handle error (e.g., show snackbar, log to analytics)
},
)
Example 2: Grid of Video Previews
Perfect for video galleries or content browsing:
GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
childAspectRatio: 16 / 9,
),
itemCount: videoUrls.length,
itemBuilder: (context, index) {
return ClipRRect(
borderRadius: BorderRadius.circular(12),
child: TssVideoGlimpse(
videoUrl: videoUrls[index],
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
quality: TssVideoQuality.medium,
),
);
},
)
Example 3: Using the Controller for Advanced Control
For scenarios where you need more control over the video preview:
class VideoPreviewPage extends StatefulWidget {
@override
_VideoPreviewPageState createState() => _VideoPreviewPageState();
}
class _VideoPreviewPageState extends State<VideoPreviewPage> {
late TssVideoGlimpseController _controller;
@override
void initState() {
super.initState();
_controller = TssVideoGlimpseController(
videoUrl: 'https://example.com/video.mp4',
quality: TssVideoQuality.high,
);
_initializeController();
}
Future<void> _initializeController() async {
final success = await _controller.initialize();
if (!success) {
// Handle initialization failure
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to load video: ${_controller.error}')),
);
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Video Preview')),
body: Column(
children: [
TssVideoGlimpse.controller(
controller: _controller,
width: double.infinity,
height: 300,
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton.icon(
onPressed: () => _controller.play(),
icon: const Icon(Icons.play_arrow),
label: const Text('Play'),
),
const SizedBox(width: 16),
ElevatedButton.icon(
onPressed: () => _controller.pause(),
icon: const Icon(Icons.pause),
label: const Text('Pause'),
),
],
),
],
),
);
}
}
Example 4: Firebase Storage with Authentication
import 'package:firebase_core/firebase_core.dart';
import 'package:tss_video_glimpse/tss_video_glimpse.dart';
class FirebaseVideoGallery extends StatelessWidget {
final List<String> firebasePaths = [
'videos/intro.mp4',
'videos/tutorial.mp4',
'videos/demo.mp4',
];
@override
Widget build(BuildContext context) {
return ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: firebasePaths.length,
itemBuilder: (context, index) {
return Card(
margin: const EdgeInsets.only(bottom: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TssVideoGlimpse.firebase(
firebasePath: firebasePaths[index],
width: double.infinity,
height: 200,
fit: BoxFit.cover,
quality: TssVideoQuality.high,
),
Padding(
padding: const EdgeInsets.all(12),
child: Text(
'Video ${index + 1}',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
],
),
);
},
);
}
}
Example 5: YouTube Video with Preview Only
Show only the thumbnail without the play button overlay:
TssVideoGlimpse(
youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
width: 300,
height: 200,
showPreviewOnly: true, // Only shows thumbnail
fit: BoxFit.cover,
)
Example 6: Responsive Video Preview
Adapts to different screen sizes:
class ResponsiveVideoPreview extends StatelessWidget {
final String videoUrl;
const ResponsiveVideoPreview({required this.videoUrl});
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final width = constraints.maxWidth;
final height = width * 9 / 16; // 16:9 aspect ratio
return TssVideoGlimpse(
videoUrl: videoUrl,
width: width,
height: height,
fit: BoxFit.cover,
quality: width > 600
? TssVideoQuality.high
: TssVideoQuality.medium,
);
},
);
}
}
⚙️ Configuration Options
| Parameter | Type | Default | Description |
|---|---|---|---|
videoUrl |
String? |
null |
Network URL of the video |
assetPath |
String? |
null |
Local asset path |
firebasePath |
String? |
null |
Firebase Storage path |
youtubeUrl |
String? |
null |
YouTube video URL |
width |
double |
200 |
Preview width in pixels |
height |
double |
150 |
Preview height in pixels |
fit |
BoxFit |
BoxFit.cover |
How the preview fits in the box |
placeholder |
Widget? |
null |
Widget shown while loading |
errorWidget |
Widget? |
null |
Widget shown on error |
onError |
Function(dynamic)? |
null |
Error callback function |
showPreviewOnly |
bool |
false |
Only shows thumbnail |
showControls |
bool |
true |
Show player controls |
cacheMaxAge |
Duration |
7 days |
Maximum cache duration |
quality |
TssVideoQuality |
medium |
Preview quality level |
Quality Levels
TssVideoQuality.low- Faster loading, lower memory usage (recommended for lists)TssVideoQuality.medium- Balanced performance and quality (default)TssVideoQuality.high- Best quality, higher memory usage (recommended for detail views)
🔥 Firebase Setup
To use Firebase Storage paths, initialize Firebase in your app:
1. Add Firebase to your project
Follow the FlutterFire documentation to add Firebase to your Flutter app.
2. Initialize Firebase
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
3. Use Firebase Storage paths
TssVideoGlimpse.firebase(
firebasePath: 'videos/my-video.mp4',
width: 300,
height: 200,
)
🛠️ Platform-Specific Setup
Android
Add to android/app/src/main/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:usesCleartextTraffic="true">
<!-- Your app configuration -->
</application>
</manifest>
iOS
Add to ios/Runner/Info.plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>io.flutter.embedded_views_preview</key>
<true/>
Web
No additional setup required! Works out of the box.
Desktop (Linux, macOS, Windows)
No additional setup required! Works out of the box.
🎯 Best Practices
1. Use Appropriate Quality Settings
// For lists and grids
TssVideoGlimpse(
videoUrl: url,
quality: TssVideoQuality.low, // Faster, less memory
)
// For detail views
TssVideoGlimpse(
videoUrl: url,
quality: TssVideoQuality.high, // Better quality
)
2. Handle Errors Gracefully
TssVideoGlimpse(
videoUrl: url,
onError: (error) {
// Log to analytics
FirebaseAnalytics.instance.logEvent(
name: 'video_load_error',
parameters: {'error': error.toString()},
);
// Show user-friendly message
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Unable to load video preview')),
);
},
)
3. Dispose Controllers Properly
@override
void dispose() {
_controller.dispose(); // Always dispose controllers
super.dispose();
}
4. Use Const Constructors When Possible
const TssVideoGlimpse(
videoUrl: 'https://example.com/video.mp4',
width: 200,
height: 150,
)
🔧 Advanced Features
Cache Management
import 'package:tss_video_glimpse/tss_video_glimpse.dart';
// Clear all cached videos
await TssVideoLoaderService().clearCache();
// Remove specific video from cache
await TssVideoLoaderService().removeFromCache(videoUrl);
Custom Cache Duration
TssVideoGlimpse(
videoUrl: url,
cacheMaxAge: const Duration(days: 30), // Cache for 30 days
)
📱 Complete Example App
Check out the example directory for a complete sample app demonstrating:
- Network video previews
- Asset video previews
- Firebase Storage integration
- Grid layouts
- Custom styling
- Error handling
- Controller usage
- Responsive design
🐛 Troubleshooting
Videos not loading on Android
Make sure you have internet permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>
Videos not loading on iOS
Check that NSAppTransportSecurity is configured in Info.plist.
Firebase videos not loading
Ensure Firebase is properly initialized and you have the correct storage rules.
🤝 Contributing
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
How to Contribute
- 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.
💖 Support
If you find this package helpful, please:
- ⭐ Star the repository on GitHub
- 👍 Like it on pub.dev
- 🐛 Report issues on our issue tracker
- 💬 Share your feedback and suggestions
🙏 Acknowledgments
Built with ❤️ using:
- omni_video_player - Powerful video player
- firebase_storage - Firebase integration
- flutter_cache_manager - Smart caching
Made with 💙 by the TSS Team
Libraries
- tss_video_glimpse
- TSS Video Glimpse - A powerful cross-platform Flutter package for generating stunning video previews and thumbnails from network URLs, asset paths, and Firebase Storage paths.