feat(playback): add embedded mpv (macos) stream recording (#916)

* feat(playback): add embedded mpv stream recording
Entire-Checkpoint: f957cd9849e0

* fix(playback): address embedded mpv recording review
Entire-Checkpoint: f957cd9849e0

* fix(playback): track mpv recording auto-stop replies
Entire-Checkpoint: f957cd9849e0
This commit is contained in:
4gray authored and GitHub committed 2026-05-10 12:27:09 +02:00
1 parent 935ed1b1a9
commit 724e4b1ab3
34 files changed
+1413 -126

No files matched your search

@@ -18,6 +18,7 @@ export interface EmbeddedMpvCapabilities {
playbackSpeed: boolean;
aspectOverride: boolean;
screenshot: boolean;
recording: boolean;
}
export interface EmbeddedMpvSupport {
@@ -38,6 +39,18 @@ export interface EmbeddedMpvAudioTrack {
export type EmbeddedMpvSubtitleTrack = EmbeddedMpvAudioTrack;
export interface EmbeddedMpvRecordingState {
active: boolean;
targetPath?: string;
startedAt?: string;
error?: string;
}
export interface EmbeddedMpvRecordingStartOptions {
directory?: string;
title?: string;
}
export interface EmbeddedMpvSession {
id: string;
title: string;
@@ -52,6 +65,7 @@ export interface EmbeddedMpvSession {
selectedSubtitleTrackId: number | null;
playbackSpeed: number;
aspectOverride: string;
recording?: EmbeddedMpvRecordingState;
startedAt: string;
updatedAt: string;
error?: string;
@@ -36,8 +36,7 @@ export const OPEN_VLC_PLAYER = 'OPEN_VLC_PLAYER';
export const SET_VLC_PLAYER_PATH = 'SET_VLC_PLAYER_PATH';
export const SET_VLC_REUSE_INSTANCE = 'SET_VLC_REUSE_INSTANCE';
export const CLOSE_EXTERNAL_PLAYER_SESSION = 'CLOSE_EXTERNAL_PLAYER_SESSION';
export const EXTERNAL_PLAYER_SESSION_UPDATE =
'EXTERNAL_PLAYER_SESSION_UPDATE';
export const EXTERNAL_PLAYER_SESSION_UPDATE = 'EXTERNAL_PLAYER_SESSION_UPDATE';
export const EMBEDDED_MPV_SUPPORT = 'EMBEDDED_MPV_SUPPORT';
export const EMBEDDED_MPV_CREATE_SESSION = 'EMBEDDED_MPV_CREATE_SESSION';
export const EMBEDDED_MPV_LOAD_PLAYBACK = 'EMBEDDED_MPV_LOAD_PLAYBACK';
@@ -50,6 +49,12 @@ export const EMBEDDED_MPV_SET_SUBTITLE_TRACK =
'EMBEDDED_MPV_SET_SUBTITLE_TRACK';
export const EMBEDDED_MPV_SET_SPEED = 'EMBEDDED_MPV_SET_SPEED';
export const EMBEDDED_MPV_SET_ASPECT = 'EMBEDDED_MPV_SET_ASPECT';
export const EMBEDDED_MPV_START_RECORDING = 'EMBEDDED_MPV_START_RECORDING';
export const EMBEDDED_MPV_STOP_RECORDING = 'EMBEDDED_MPV_STOP_RECORDING';
export const EMBEDDED_MPV_GET_DEFAULT_RECORDING_FOLDER =
'EMBEDDED_MPV_GET_DEFAULT_RECORDING_FOLDER';
export const EMBEDDED_MPV_SELECT_RECORDING_FOLDER =
'EMBEDDED_MPV_SELECT_RECORDING_FOLDER';
export const EMBEDDED_MPV_DISPOSE_SESSION = 'EMBEDDED_MPV_DISPOSE_SESSION';
export const EMBEDDED_MPV_SESSION_UPDATE = 'EMBEDDED_MPV_SESSION_UPDATE';
export const EMBEDDED_MPV_PREPARE = 'EMBEDDED_MPV_PREPARE';
@@ -1,10 +1,9 @@
import { PlaybackPositionData } from './playback-position.interface';
export interface PlayerContentInfo
extends Omit<
PlaybackPositionData,
'positionSeconds' | 'durationSeconds' | 'updatedAt'
> {
export interface PlayerContentInfo extends Omit<
PlaybackPositionData,
'positionSeconds' | 'durationSeconds' | 'updatedAt'
> {
playlistId: string;
}
@@ -12,6 +11,7 @@ export interface ResolvedPortalPlayback {
streamUrl: string;
title: string;
thumbnail?: string | null;
isLive?: boolean;
startTime?: number;
contentInfo?: PlayerContentInfo;
headers?: Record<string, string>;
@@ -44,6 +44,8 @@ export interface Settings {
remoteControlPort: number;
/** Custom download folder path (uses system Downloads folder if not set) */
downloadFolder?: string;
/** Custom live recording folder path (uses system Downloads folder if not set) */
recordingFolder?: string;
/** Cover/poster sizing preset applied across grids and rails */
coverSize?: CoverSize;
/**