SubtitleEdit/subtitleedit · error · InvalidOperationException

Failed to initialize mpv: {_mpvContext.GetErrorString(err)}

Error message

Failed to initialize mpv: {_mpvContext.GetErrorString(err)}

What it means

Thrown inside ReviewSpeechHistoryViewModel.PlayAudio when LibMpvDynamicPlayer.Initialize() returns a negative mpv error code while preparing a history-entry audio preview. Same root cause shape as the Review Speech dialog, but this PlayAudio (lines 101-120) has NO try/catch around the lock/Initialize block — unlike error 301 — so the InvalidOperationException propagates to the caller (PlayItem). The history dialog relies on the caller or a higher-level handler to absorb it; otherwise playback state can be left inconsistent.

Source

Thrown at src/ui/Features/Video/TextToSpeech/ReviewSpeechHistory/ReviewSpeechHistoryViewModel.cs:113

        {
            row.IsPlaying = false;
            row.IsPlayingEnabled = true;
        }
    }

    private async Task PlayAudio(string fileName)
    {
        lock (_playLock)
        {
            _mpvContext?.Stop();
            _mpvContext?.Dispose();

            _mpvContext = new LibMpvDynamicPlayer();
            _mpvContext.LoadLib(); // core not initialized"
            var err = _mpvContext.Initialize();
            if (err < 0)
            {
                throw new InvalidOperationException($"Failed to initialize mpv: {_mpvContext.GetErrorString(err)}");
            }
        }

        await _mpvContext.LoadAudio(fileName);

        _timer.Start();
    }

    [RelayCommand]
    private void Ok()
    {
        OkPressed = true;
        Window?.Close();
    }

    [RelayCommand]
    private void Cancel()
    {

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Check the SeLogger / application log for the GetErrorString(err) text embedded in the message.
  2. Confirm libmpv arch/bitness matches the process and the C++ runtime is installed.
  3. Re-fetch libmpv via SE's player download.
  4. Wrap this PlayAudio in the same try/catch + UI-reset pattern already used in ReviewSpeechViewModel (error 301) so the history rows do not get stranded.

Example fix

// before - exception escapes, can leave history rows disabled
lock (_playLock)
{
    _mpvContext = new LibMpvDynamicPlayer();
    _mpvContext.LoadLib();
    var err = _mpvContext.Initialize();
    if (err < 0) throw new InvalidOperationException($"Failed to initialize mpv: {_mpvContext.GetErrorString(err)}");
}
await _mpvContext.LoadAudio(fileName);

// after - mirror the defensive catch from ReviewSpeechViewModel
try
{
    lock (_playLock) { /* ...init as above... */ }
    await _mpvContext.LoadAudio(fileName);
}
catch (Exception ex)
{
    SeLogger.Error(ex, $"ReviewSpeechHistory: unable to play \"{fileName}\"");
    ResetPlaybackUiState();
}
Defensive patterns

Strategy: try-catch

Validate before calling

_mpvContext = new LibMpvDynamicPlayer();
if (!_mpvContext.CanLoad()) { SeLogger.Error("libmpv not found (history preview)"); return; }

Try / catch

// This site currently lacks a local catch - add one mirroring ReviewSpeechViewModel:
try
{
    lock (_playLock) { /* init as above */ }
    await _mpvContext.LoadAudio(fileName);
}
catch (Exception ex)
{
    SeLogger.Error(ex, $"ReviewSpeechHistory: unable to play \"{fileName}\"");
    ResetPlaybackUiState();
}

Prevention

When it happens

Trigger: LoadLib() found libmpv but mpv_initialize failed: wrong-bitness/arch libmpv, missing C++ runtime dependency, corrupt libmpv, or an init-time option rejected by mpv. Distinct from a missing file (the caller guards missing FileName/File.Exists before reaching here).

Common situations: Same libmpv misconfiguration as 301 but surfaced through the Review Speech History window; a machine where libmpv loads but cannot initialize (e.g. sandboxed without GPU/render access, missing runtime).

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/29a86d2bf05a14ad. Report an issue: GitHub.