fix: remove unsafe libmpv setProperty FFI calls causing SIGSEGV crash (v3.1.7)
Build and Release / Build Windows x64 (push) Has been cancelled

This commit is contained in:
2026-09-04 23:17:15 +03:00
parent 15bebd6e47
commit 1395cfd414
5 changed files with 33 additions and 23 deletions
+1 -1
View File
@@ -10,7 +10,7 @@
</p> </p>
<p align="center"> <p align="center">
<a href="https://github.com/RarDog/Lunaris/releases"><img src="https://img.shields.io/badge/Version-3.1.6-8A2BE2?style=for-the-badge&logo=semver&logoColor=white" alt="Version 3.1.6" /></a> <a href="https://github.com/RarDog/Lunaris/releases"><img src="https://img.shields.io/badge/Version-3.1.7-8A2BE2?style=for-the-badge&logo=semver&logoColor=white" alt="Version 3.1.7" /></a>
<img src="https://img.shields.io/badge/Flutter-3.47+-02569B?style=for-the-badge&logo=flutter&logoColor=white" alt="Flutter" /> <img src="https://img.shields.io/badge/Flutter-3.47+-02569B?style=for-the-badge&logo=flutter&logoColor=white" alt="Flutter" />
<img src="https://img.shields.io/badge/Platform-Android%20%7C%20Linux%20%7C%20Windows-00C853?style=for-the-badge" alt="Platforms" /> <img src="https://img.shields.io/badge/Platform-Android%20%7C%20Linux%20%7C%20Windows-00C853?style=for-the-badge" alt="Platforms" />
<a href="https://github.com/RarDog/Lunaris/wiki"><img src="https://img.shields.io/badge/Wiki-Documentation-FF6F00?style=for-the-badge&logo=gitbook&logoColor=white" alt="Wiki" /></a> <a href="https://github.com/RarDog/Lunaris/wiki"><img src="https://img.shields.io/badge/Wiki-Documentation-FF6F00?style=for-the-badge&logo=gitbook&logoColor=white" alt="Wiki" /></a>
+2 -2
View File
@@ -1,3 +1,3 @@
const appDisplayVersion = '3.1.6'; const appDisplayVersion = '3.1.7';
const appBuildNumber = 67; const appBuildNumber = 68;
const appReleaseChannel = 'Stable'; const appReleaseChannel = 'Stable';
+9
View File
@@ -1,4 +1,13 @@
const lunarisChangelog = [ const lunarisChangelog = [
LunarisChange(
version: '3.1.7',
title: 'Устранение критического сбоя при открытии видеопоста (SIGSEGV в libmpv)',
bullets: [
'Устранение нативного вылета: полностью удалены небезопасные прямые FFI-вызовы setProperty к mpv, приводившие к немедленному падению приложения на Android при инициализации видео.',
'Безопасная конфигурация декодирования: перевод настроек аппаратного ускорения и фоллбэка кодеков на официальный типобезопасный VideoControllerConfiguration (media_kit_video).',
'Надежный фоллбэк при редких ошибках кодека: при несовместимости аппаратного декодера плеер бесшовно переключается на программный FFmpeg-декодер без риска краша.',
],
),
LunarisChange( LunarisChange(
version: '3.1.6', version: '3.1.6',
title: 'Надежный полноэкранный плеер, сохранение провайдеров в поиске, громкость и устранение ошибки кодека', title: 'Надежный полноэкранный плеер, сохранение провайдеров в поиске, громкость и устранение ошибки кодека',
@@ -75,6 +75,7 @@ class _PostMediaViewerState extends State<PostMediaViewer>
late double _currentVolume; late double _currentVolume;
String? _videoError; String? _videoError;
bool _retriedFormatError = false; bool _retriedFormatError = false;
bool _softwareDecodingFallback = false;
Timer? _hideTimer; Timer? _hideTimer;
StreamSubscription<String>? _errorSubscription; StreamSubscription<String>? _errorSubscription;
StreamSubscription<Duration>? _positionSubscription; StreamSubscription<Duration>? _positionSubscription;
@@ -105,6 +106,7 @@ class _PostMediaViewerState extends State<PostMediaViewer>
_videoIndex = 0; _videoIndex = 0;
_videoError = null; _videoError = null;
_retriedFormatError = false; _retriedFormatError = false;
_softwareDecodingFallback = false;
_imageUrls = _buildImageUrls(widget.post); _imageUrls = _buildImageUrls(widget.post);
_videoUrls = _buildVideoUrls(widget.post); _videoUrls = _buildVideoUrls(widget.post);
if (_isVideo(widget.post) && _videoUrls.isNotEmpty) { if (_isVideo(widget.post) && _videoUrls.isNotEmpty) {
@@ -359,13 +361,13 @@ class _PostMediaViewerState extends State<PostMediaViewer>
void _initializeVideo() { void _initializeVideo() {
MediaKit.ensureInitialized(); MediaKit.ensureInitialized();
_player = Player(); _player = Player();
_controller = VideoController(_player!); _controller = VideoController(
try { _player!,
final native = _player!.platform as dynamic; configuration: VideoControllerConfiguration(
native?.setProperty('hwdec', 'auto-safe', waitForInitialization: false); enableHardwareAcceleration: !_softwareDecodingFallback,
native?.setProperty('vd-lavc-software-fallback', 'yes', waitForInitialization: false); hwdec: _softwareDecodingFallback ? 'no' : 'auto-safe',
native?.setProperty('vd-lavc-check-hw-profile', 'yes', waitForInitialization: false); ),
} catch (_) {} );
_applyVolume(); _applyVolume();
_player!.setPlaylistMode( _player!.setPlaylistMode(
_loopVideo ? PlaylistMode.single : PlaylistMode.none, _loopVideo ? PlaylistMode.single : PlaylistMode.none,
@@ -437,14 +439,12 @@ class _PostMediaViewerState extends State<PostMediaViewer>
lower.contains('stream format not recognized') || lower.contains('stream format not recognized') ||
lower.contains('failed to recognize file format'))) { lower.contains('failed to recognize file format'))) {
_retriedFormatError = true; _retriedFormatError = true;
try { _softwareDecodingFallback = true;
final native = _player?.platform as dynamic; _disposeVideo();
await native?.setProperty('hwdec', 'no', waitForInitialization: false); await Future<void>.delayed(const Duration(milliseconds: 250));
} catch (_) {} if (mounted) {
await Future<void>.delayed(const Duration(milliseconds: 300));
if (mounted && _player != null) {
_videoIndex = 0; _videoIndex = 0;
await _openVideo(play: play); _initializeVideo();
return; return;
} }
} }
@@ -456,11 +456,12 @@ class _PostMediaViewerState extends State<PostMediaViewer>
Future<void> _retryVideo() async { Future<void> _retryVideo() async {
_videoIndex = 0; _videoIndex = 0;
_retriedFormatError = false; _retriedFormatError = false;
try { _softwareDecodingFallback = true;
final native = _player?.platform as dynamic; _disposeVideo();
await native?.setProperty('hwdec', 'no', waitForInitialization: false); await Future<void>.delayed(const Duration(milliseconds: 150));
} catch (_) {} if (mounted) {
await _openVideo(play: true); _initializeVideo();
}
} }
void _disposeVideo() { void _disposeVideo() {
+1 -1
View File
@@ -1,7 +1,7 @@
name: gel_rule_app name: gel_rule_app
description: Local backend/core layer for a Flutter booru browser app. description: Local backend/core layer for a Flutter booru browser app.
publish_to: "none" publish_to: "none"
version: 3.1.6+67 version: 3.1.7+68
environment: environment:
sdk: ">=3.3.0 <4.0.0" sdk: ">=3.3.0 <4.0.0"