Files
iptvnator/libs/shared/interfaces/src/lib/embedded-mpv-extra-options.util.spec.ts
T
ZoultandClaude Fable 5.1 5a11b82eaf feat(embedded-mpv): configurable extra libmpv options and network auto-reconnect (#1515)
Extra libmpv options (Settings > Playback) reach every embedded engine off the command line (createSession array on Windows/macOS, a 0600 --include file on Linux native-view, a stdin preamble for the frame-copy helper); the keys the embed depends on are refused, and keys libmpv rejects are reported once per session. Dropped streams reload automatically (error, or ended on live) with 2 s -> 30 s backoff, six attempts per outage and a 30 s stability reset, only for a load that already played; engine failures stay terminal, a running recording is filed as interrupted and restarted after the reload, and an external subtitle file is re-added. Settings.embeddedMpvAutoReconnect (default on) opts out; the player shows 'Reconnecting... attempt N of M'.

Started by Bpl5966 in #1515 and finished by the maintainers in the same PR.

Co-authored-by: Bpl5966 <amine.b1959@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 16:36:14 +02:00

84 lines
3.0 KiB
TypeScript

import {
EMBEDDED_MPV_NETWORK_DEFAULT_OPTIONS,
normalizeEmbeddedMpvExtraOptions,
parseEmbeddedMpvExtraOptions,
resolveEmbeddedMpvSessionOptionArguments,
validateEmbeddedMpvExtraOptions,
} from './embedded-mpv-extra-options.util';
describe('embedded MPV extra options', () => {
it('parses one key=value pair per line and tolerates CRLF, spaces and a -- prefix', () => {
expect(
parseEmbeddedMpvExtraOptions(
'hwdec = auto-safe\r\n\n --cache-secs=30 \ndemuxer-lavf-o=reconnect=1,reconnect_delay_max=5'
)
).toEqual([
{ key: 'hwdec', value: 'auto-safe' },
{ key: 'cache-secs', value: '30' },
{
key: 'demuxer-lavf-o',
value: 'reconnect=1,reconnect_delay_max=5',
},
]);
});
it('skips lines without a value or with a malformed key', () => {
expect(
parseEmbeddedMpvExtraOptions(
'hwdec=\nno-border\n=auto\n bad key=1\nvolume=50'
)
).toEqual([{ key: 'volume', value: '50' }]);
});
it('normalizes to canonical lines but keeps malformed lines for the user to fix', () => {
expect(
normalizeEmbeddedMpvExtraOptions(
' --hwdec = auto \n\nnot an option\n'
)
).toBe('hwdec=auto\nnot an option');
expect(normalizeEmbeddedMpvExtraOptions(undefined)).toBe('');
expect(normalizeEmbeddedMpvExtraOptions(['a=1', '', 'b=2'])).toBe(
'a=1\nb=2'
);
});
it('reports malformed lines and forbidden keys separately', () => {
expect(validateEmbeddedMpvExtraOptions('')).toBeNull();
expect(validateEmbeddedMpvExtraOptions(undefined)).toBeNull();
expect(validateEmbeddedMpvExtraOptions('hwdec=auto')).toBeNull();
expect(
validateEmbeddedMpvExtraOptions(
'hwdec=auto\noops\nvo=null\nwid=1\nvo=gpu'
)
).toEqual({ invalidLines: ['oops'], forbiddenKeys: ['vo', 'wid'] });
expect(
validateEmbeddedMpvExtraOptions('input-ipc-server=/tmp/s')
).toEqual({
forbiddenKeys: ['input-ipc-server'],
});
});
it('prepends the network defaults and drops forbidden keys for the addon', () => {
expect(resolveEmbeddedMpvSessionOptionArguments('')).toEqual([
...EMBEDDED_MPV_NETWORK_DEFAULT_OPTIONS,
]);
expect(
resolveEmbeddedMpvSessionOptionArguments(
'wid=42\nhwdec=no\nnetwork-timeout=3\nbroken line'
)
).toEqual([
...EMBEDDED_MPV_NETWORK_DEFAULT_OPTIONS,
'hwdec=no',
'network-timeout=3',
]);
});
it('keeps the user override after the default it replaces', () => {
const options =
resolveEmbeddedMpvSessionOptionArguments('network-timeout=3');
expect(options.indexOf('network-timeout=10')).toBeLessThan(
options.indexOf('network-timeout=3')
);
});
});