📺 tha_player
Native, network‑only video player for Flutter with modern MX/VLC‑style UX. Android uses ExoPlayer; iOS uses AVPlayer. Includes gestures, thumbnails on seek, DRM (Android), fullscreen, BoxFit, and more.
✨ Features
- âś… Native engines: ExoPlayer (Android) and AVPlayer (iOS)
- ✅ Gestures: tap to show/hide, double‑tap seek, long‑press skip, horizontal scrub, vertical volume/brightness
- âś… Controls: play/pause, speed, fullscreen (manual or auto), lock, BoxFit (contain/cover/fill/fitWidth/fitHeight)
- âś… Quality, audio, and subtitle track selection with data saver toggle
- âś… Configurable retry/backoff, error callbacks, PiP playback controls
- âś… Thumbnails: WebVTT sprites or image sequences during seek preview (cached in-memory)
- âś… DRM (Android): Widevine and ClearKey
- âś… M3U playlist parsing utility
- âś… Overlay support (watermark, logos)
📦 Install
Add to pubspec.yaml
:
dependencies:
tha_player: ^0.4.0
Then:
flutter pub get
🚀 Quick Start
import 'package:tha_player/tha_player.dart';
final ctrl = ThaNativePlayerController.single(
ThaMediaSource(
'https://storage.flutter-io.cn/gtv-videos-bucket/sample/BigBuckBunny.mp4',
// Optional VTT thumbnails
// thumbnailVttUrl: 'https://example.com/thumbs.vtt',
),
autoPlay: true,
playbackOptions: ThaPlaybackOptions(
maxRetryCount: 5,
initialRetryDelay: Duration(milliseconds: 800),
),
);
// In build:
AspectRatio(
aspectRatio: 16 / 9,
child: ThaModernPlayer(
controller: ctrl,
doubleTapSeek: Duration(seconds: 10),
longPressSeek: Duration(seconds: 3),
autoHideAfter: Duration(seconds: 3),
initialBoxFit: BoxFit.contain,
),
)
Fullscreen
Tap the fullscreen icon in the control bar. Playback position and state are preserved when entering/exiting fullscreen.
BoxFit
Choose between contain
, cover
, fill
, fitWidth
, and fitHeight
from the menu.
Track Selection
Use the control bar to switch quality, audio, or subtitle tracks at runtime. You can also fetch tracks directly:
final qualities = await ctrl.getVideoTracks();
final audios = await ctrl.getAudioTracks();
final subtitles = await ctrl.getSubtitleTracks();
await ctrl.selectAudioTrack(audios.first.id);
await ctrl.selectSubtitleTrack(null); // disable captions
Lock Controls
Use the lock icon to prevent controls/gestures; unlock with the floating button.
DRM (Android)
final ctrl = ThaNativePlayerController.single(
ThaMediaSource(
'https://my.cdn.com/drm/manifest.mpd',
drm: ThaDrmConfig(
type: ThaDrmType.widevine, // or ThaDrmType.clearKey
licenseUrl: 'https://license.server/wv',
headers: {'Authorization': 'Bearer <token>'},
// clearKey: '{"keys":[{"kty":"oct","k":"...","kid":"..."}]}'
),
),
);
Thumbnails (WebVTT)
Provide a .vtt
with sprites or images and optional #xywh
regions:
ThaMediaSource(
'https://example.com/video.m3u8',
thumbnailVttUrl: 'https://example.com/thumbs.vtt',
)
đź› Platform Notes
- Android: ExoPlayer backend with Media3; Widevine/ClearKey supported; per‑item HTTP headers.
- iOS: AVPlayer backend;
fitWidth
/fitHeight
approximate viaresizeAspect
. - Keep‑screen‑on is enabled during playback (Android/iOS).
- Playability depends on device codecs, stream, and network.
Thumbnails are cached in-memory. Call clearThumbnailCache()
if you need to purge the cache.
Resilient playback
ThaPlaybackOptions
lets you tweak retry/backoff behaviour and rebuffer handling. Failures are surfaced via ThaNativeEvents.error
and the onError
callback on ThaModernPlayer
.
Custom HTTP (Android)
Provide a bespoke OkHttpClient
to inject interceptors or caching:
Register the factory inside your Android Application
:
class App : FlutterApplication() {
override fun onCreate() {
super.onCreate()
ThaPlayerPlugin.setHttpClientFactory {
OkHttpClient.Builder()
.addInterceptor(MyHeaderInterceptor())
.cache(Cache(cacheDir.resolve("video"), 100L * 1024L * 1024L))
.build()
}
}
}
Set the factory before creating any Flutter controllers so every instance shares the same client.
16 KB Page Size Support
This plugin does not ship custom native decoder binaries. If you add native libraries, link them with a max page size compatible with 16 KB systems (e.g., -Wl,-z,max-page-size=16384
on Android NDK).
đź§Ş Example
See example/
for a runnable app that demonstrates the modern controls, gestures, fullscreen, and thumbnails.
đź’– Support
If this package helps you, consider a tip:
- Tron (TRC20):
TLbwVrZyaZujcTCXAb94t6k7BrvChVfxzi
📣 Contributing
Issues and PRs are welcome! Please file bugs or ideas at the issue tracker.
đź“„ License
MIT — see LICENSE
.
Libraries
- tha_player
- Top-level library export for tha_player.
- tha_player_method_channel
- tha_player_platform_interface