gstplayer 0.0.3
gstplayer: ^0.0.3 copied to clipboard
A polished, all-in-one Flutter video player powered by GStreamer — beautiful built-in controls and broad format support for local and network video on mobile and desktop.
0.0.3 #
UI (Flutter 3.44 / material_ui) #
- Dart widgets import
package:material_ui/material_ui.dartinstead ofpackage:flutter/material.dart. - Removed
chat_context_menu; speed and top-bar menus use a first-party Overlay. - Example no longer depends on
cupertino_icons.
Bottom chrome & settings #
- Side lock/unlock on the same row as the center play/pause (far right). Locking hides the bottom chrome (and top/center controls) and blocks gestures and keyboard shortcuts; tap only shows/hides the unlock button.
- Two-row Bilibili chrome: transport (play, position, progress, remaining time, speed, settings, volume, fullscreen) plus danmaku / send / CC.
- Two-level settings popup: mirror, single-episode loop, autoplay, play-next, 16:9 / 4:3, hide black bars, lights-off, audio tracks.
- Chrome copy via
GstVideoView.language(GstPlayerLanguage.zh/.en). - Screenshot is no longer on the chrome (
showCaptureButtonkept for API compatibility; hosts can still useonScreenshot/captureCurrentFrame).
GstVideoView #
- New:
language,onPlayNext,onLightsOffChanged. - EOS with looping off and play-next enabled calls
onPlayNext. - Mirror, forced aspect, hide-black-bars, and lights-off overlay follow chrome settings.
Darwin / Swift Package Manager #
- Example iOS and macOS are SPM-only (no CocoaPods
Podfile). - Plugin
pubspec.yamlsetsenable-swift-package-manager: truesopub getdoes not recreate a Podfile when the global Flutter config has SPM disabled. - SPM macOS hosts embed
GStreamer.frameworkwith an Xcode Run Script (macos/scripts/embed_gstreamer_framework.sh). CocoaPods hosts can still usemacos/gstreamer_podfile_helper.rb.
0.0.2 #
Playback stability (Android) #
- Android video sink is display-only:
glupload → glcolorconvert → glvideoflip → queue → glimagesink. - Removed the main-pipeline capture tee
(
tee → gldownload → videoconvert → capsfilter → appsink). That branch competed with MediaCodec / External-OES under rapid play/pause and caused_amc_gl_wait, frozen video, and flush failures. gst_element_set_statefor play/pause/stop no longer blocks up to 5s onget_state; UI converges via busSTATE_CHANGED.BUFFERINGforced PAUSED/PLAYING applies only to URI/network streams (is_uri); local/asset transient buffering no longer interrupts decode.appsinksample callback returnsGST_FLOW_OKon drop instead ofGST_FLOW_ERROR, so a bad capture frame cannot tear down the pipeline.- Dart transport: play/pause intent coalesce with 200ms debounce, so rapid toggles send only the latest intent to native (tests updated accordingly).
Screenshot / thumbnail #
- Android
captureFramePng()uses headlessGstPlayer.captureThumbnail(no live appsink on the display sink). - Native
gstp_thumbnail_capturefollows GStreamer officialsnapshot.cflow:uridecodebin → videoconvert → videoscale → appsink, thenPAUSED→ seek (KEY_UNIT | FLUSH) →pull-preroll. - Android thumbnail extras (still GStreamer decodebin APIs):
autoplug-continue: skip audio/text soamcaudiodecis never created (avoidsDownstream returned not-linked/code should not be reachedSIGABRT).force-sw-decoders=true: prefer libav so appsink gets system-memory frames (AMC video is GL-only: “Codec only supports GL output but downstream does not”).
- iOS / desktop still prefer
captureCurrentFrame()(appsink), with thumbnail fallback on failure. - Screenshot keeps using GStreamer only (no Flutter
PixelCopypath).
Controls & scrub preview #
- Bilibili-style bottom chrome: play, danmaku input, danmaku/subtitle toggles, screenshot, fullscreen; overlay mode uses a compact row (overflow fixed).
- Scrub preview is external (GSY-style WebVTT + sprite / frame list),
shown only while dragging — no live
captureThumbnailon the scrub path. ScrubPreviewTracksupportsassets/WebVTT and sprite paths.- Example ships
assets/sample_preview.vtt+assets/preview/sprite.jpg. - Removed example dedicated thumbnail/cover extraction page
(
thumbnail_page.dart) and in-playback cover-grab UX from the sample app. - Thumbnail work runs on
FfiThumbnailWorker(dedicated isolate) so scrub / capture does not block play/pause/seek on the transport worker.
API / example #
GstVideoView/ controls expose overlay callbacks and keepshowCaptureButton: true.- Example demonstrates external scrub preview, bottom-bar danmaku, and
screenshot dialog via
captureFramePng().
Tests #
- Playback session: rapid toggle coalesce / late pause-event races.
- Scrub preview controller and progress-bar-with-preview widgets.
- FFI thumbnail worker smoke tests.
0.0.1 #
Features #
- Cross-platform Flutter video player driven by a native C GStreamer core and
Dart FFI (
GstPlayer/GstPlayerController/GstVideoView). - Playback: open (network / file / asset), play / pause / stop / seek, volume, mute, speed, looping; reactive state, position, duration, resolution, buffering, EOS, and error reporting.
- Platform rendering:
- Android:
glupload→glcolorconvert→glvideoflip→tee→glimagesinkviaSurfaceProducer/ VideoOverlay; capture tee viagldownload→appsink. - iOS / macOS:
appsink(BGRA) →FlutterTexture/ IOSurface. - Windows / Linux:
appsink(BGRA) → pixel-buffer textures.
- Android:
- HTTPS / HTTP sources use patched
reqwesthttpsrc(current_thread Tokio on Android) instead ofsouphttpsrc. GstPlayer.initialize()is kickoff-only;ensureReady()(and controller create / thumbnail capture) await full runtime readiness so the UI isolate is not blocked ongst_init.GstPlayer.captureThumbnailandGstPlayerController.captureCurrentFramefor one-shot / current-frame PNG capture.- Built-in Material / Cupertino controls, immersive gestures, aspect ratio and rotation helpers.
Scripts #
- Android umbrella: default GStreamer SDK 1.28.5; default
gst-plugins-rs0.15.3 when rebuildinglibgstreqwest.a. build_reqwest_plugin_android.sh: after installing the cargo-builtlibgstreqwest.a, striplibgstrsworkspace.lafromlibgstreqwest.la. The Android SDK shipslibgstrsworkspace.awithout a matching.la; ndk-build’s libtool path otherwise passes a baregstrsworkspacetoclang++and the umbrella link fails. Cargo’s staticlib already embeds the Rust workspace crates, so the extra.ladependency is unnecessary.- Android / macOS GStreamer helper scripts share cache roots under
*/Caches/gstplayer/gstreamer/...(override withGSTREAMER_ROOT_ANDROID/GSTPLAYER_GSTREAMER_ROOTas before).
Bug fixes #
- Example Android: align
MainActivitypackage withcom.example.gstplayer_exampleand apply the Kotlin Android Gradle plugin so the launcher Activity is present in the APK. - Android ndk-build of
libgstreamer_android.sono longer fails withclang++: no such file or directory: 'gstrsworkspace'when linking the patched reqwest plugin.