flutter player issue Error during detachFromGLContext
this issue keeps appearing in my firebase crashlyst console i am playing m3u8 file from network using flutter_vlc_player: org.videolan.libvlc.AWindow$SurfaceTextureThread.detachFromGLContext
Fatal Exception: java.lang.RuntimeException Error during detachFromGLContext (see logcat for details) android.graphics.SurfaceTexture.detachFromGLContext (SurfaceTexture.java:274) org.videolan.libvlc.AWindow$SurfaceTextureThread.detachFromGLContext (Unknown Source:40) org.videolan.libvlc.AWindow$SurfaceTextureThread.access$1600 org.videolan.libvlc.AWindow.SurfaceTexture_detachFromGLContext (Unknown Source:2)
class LivestreamPlayer extends StatefulWidget { final String downstreamUrl; final String thumbnail; final String postId; final String pageType; final int width; final int height;
const LivestreamPlayer({ Key? key, required this.downstreamUrl, required this.thumbnail, required this.postId, required this.pageType, required this.width, required this.height, }) : super(key: key);
@override LivestreamPlayerState createState() => LivestreamPlayerState(); }
class LivestreamPlayerState extends State<LivestreamPlayer> { static const _aspectRatio = 16 / 9;
late VlcPlayerController controller;
double sliderValue = 0.0; double volumeValue = 50; String position = ''; String duration = ''; int numberOfCaptions = 0; int numberOfAudioTracks = 0; bool validPosition = false; String pauseState = "auto";
@override void initState() { super.initState(); _initializeController(); }
_initializeController() async { controller = VlcPlayerController.network( widget.downstreamUrl, hwAcc: HwAcc.auto, autoPlay: false, autoInitialize: true, options: VlcPlayerOptions( sout: VlcStreamOutputOptions( [VlcStreamOutputOptions.soutMuxCaching(2000)]), advanced: VlcAdvancedOptions([ VlcAdvancedOptions.networkCaching(2000), VlcVideoOptions.dropLateFrames(true), VlcAdvancedOptions.liveCaching(2000), VlcAdvancedOptions.fileCaching(1000), VlcAdvancedOptions.clockSynchronization(0), VlcAdvancedOptions.clockJitter(0), ]), extras: [ ':network-caching=1000', ':clock-jitter=0', ':clock-synchro=0', '--h264-fps=10' ], ), );
controller.addListener(_listener);
}
void _listener() { if (mounted) { if (controller.value.isInitialized) { final oPosition = controller.value.position; final oDuration = controller.value.duration; if (oDuration.inHours == 0) { final strPosition = oPosition.toString().split('.').first; final strDuration = oDuration.toString().split('.').first; setState(() { position = "${strPosition.split(':')[1]}:${strPosition.split(':')[2]}"; duration = "${strDuration.split(':')[1]}:${strDuration.split(':')[2]}"; }); } else { setState(() { position = oPosition.toString().split('.').first; duration = oDuration.toString().split('.').first; }); } setState(() { validPosition = oDuration.compareTo(oPosition) >= 0; sliderValue = validPosition ? oPosition.inSeconds.toDouble() : 0; }); setState(() { numberOfCaptions = controller.value.spuTracksCount; numberOfAudioTracks = controller.value.audioTracksCount; }); } } }
@override void dispose() async { if (controller.value.isInitialized) { controller.removeListener(_listener); controller.removeListener(_initListener);
// Pause and stop the player before disposing
await controller.stop();
await controller.stopRendererScanning();
await controller.dispose();
}
super.dispose();
}
@override void deactivate() async { await controller.stop(); await controller.stopRendererScanning(); await controller.dispose(); super.deactivate(); }
void _setSoundVolume(double value) { setState(() { volumeValue = value; }); controller.setVolume(volumeValue.toInt()); }
void _onSliderPositionChanged(double progress) { setState(() { sliderValue = progress.floor().toDouble(); }); controller.setTime(sliderValue.toInt() * Duration.millisecondsPerSecond); }
void _resetPosition() { setState(() { sliderValue = 0.0; }); controller.setTime(0); }
@override Widget build(BuildContext context) { return VisibilityDetector( key: ObjectKey(widget.postId), onVisibilityChanged: (visibilityInfo) async { if (mounted) { if (controller.value.isInitialized) { if (visibilityInfo.visibleFraction > 0.1) { if (!controller.value.isPlaying) { if (mounted) { await controller.play(); await controller.setVolume(100); setState(() { pauseState = "auto"; }); } } } else { if (mounted) { await controller.setVolume(0); if (widget.pageType != 'scapes') { await controller.pause(); _resetPosition(); } else { await controller.stop(); } } } } } }, child: SizedBox( width: MediaQuery.of(context).size.width, height: widget.pageType == 'scapes' ? MediaQuery.of(context).size.height - 60 : (1024 / 576) * MediaQuery.of(context).size.width, child: Stack( children: [ // Video player SizedBox( width: MediaQuery.of(context).size.width, height: widget.pageType == 'scapes' ? MediaQuery.of(context).size.height - 60 : (1024 / 576) * MediaQuery.of(context).size.width, child: VlcPlayer( controller: controller, aspectRatio: _aspectRatio, placeholder: const Center( child: CircularProgressIndicator( strokeWidth: 1.0, valueColor: AlwaysStoppedAnimation<Color>( ThemeColors.accentColor, ), ), ), ), ), ControlsOverlay( controller: controller, thumbnail: widget.thumbnail, width: MediaQuery.of(context).size.width.toInt(), height: widget.height, pagetype: widget.pageType, pauseState: pauseState, ), Positioned( bottom: 0, left: 0, right: 0, child: SizedBox( height: 10, child: SliderTheme( data: SliderThemeData( trackHeight: 3, thumbShape: SliderComponentShape.noThumb, trackShape: SliderCustomTrackShape(), ), child: Slider( activeColor: ThemeColors.accentColor, inactiveColor: Colors.black45, value: sliderValue, max: !validPosition ? 1.0 : controller!.value.duration.inSeconds.toDouble(), onChanged: validPosition ? _onSliderPositionChanged : null, semanticFormatterCallback: (double newValue) { return '${newValue.round()}'; }, ), ), ), ), Positioned( bottom: 35, right: 10, child: GestureDetector( onTap: () { _setSoundVolume(volumeValue == 0 ? 100 : 0); }, child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.black.withOpacity(0.5), borderRadius: BorderRadius.circular(50), ), child: Icon( volumeValue == 0 ? Icons.volume_off : Icons.volume_up, color: Colors.white, ), ), ), ), ], ), )); } }
class SliderCustomTrackShape extends RoundedRectSliderTrackShape { @override Rect getPreferredRect({ required RenderBox parentBox, Offset offset = Offset.zero, required SliderThemeData sliderTheme, bool isEnabled = false, bool isDiscrete = false, }) { final double? trackHeight = sliderTheme.trackHeight; final double trackLeft = offset.dx; final double trackTop = offset.dy + (parentBox.size.height - trackHeight!) / 2; final double trackWidth = parentBox.size.width; return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight); } }
i am also getting this exact error when running the player on android 12
i am also getting this exact error when running the player on
Device
Brand:Honor
Model:Honor 400 Lite
Orientation:Landscape
RAM free: 2.52 GB
Disk free: 175.49 GB
Operating System
Version:Android 15
Orientation:Landscape
Rooted: No
Crash
Date:Aug 17, 2025, 5:26:30 PM
App version:1.0.3 (8)
I have the same problem.