mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-19 21:18:06 +02:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6c7184475 | ||
|
|
175cff560c | ||
|
|
e5079127ab | ||
|
|
4e453850ae | ||
|
|
85a8d16542 |
No files matched your search
@@ -2,6 +2,15 @@
|
||||
|
||||
## Non publié
|
||||
|
||||
### ▶️ Lecture vidéo
|
||||
- **Fix du son manquant sur certaines chaînes** : nouvelle route `/api/live/<id>/turbo.ts` pour le zapping — vidéo copiée telle quelle, audio systématiquement réencodé en AAC côté serveur. Les chaînes en AC-3/E-AC-3/MP2 (que mpegts.js ne décode pas) ont maintenant du son, sans coût de transcodage vidéo
|
||||
- **Players mis à jour** : hls.js 1.6.7 → 1.7.1, mpegts.js 1.7.3 → 1.8.2 (vendorisés)
|
||||
- **Démarrage plus rapide** : sonde FFmpeg bornée (`-fflags nobuffer`, probesize réduit) sur le live et le turbo ; probesize VOD 10 Mo → 5 Mo ; preset live `high` et lecture d'enregistrement en `veryfast` (medium ne tenait pas le temps réel) ; détection de playlist toutes les 100 ms au lieu de 500 ms ; suppression du cache-buster qui re-téléchargeait player.html à chaque zap (les .html passent en no-cache serveur)
|
||||
- **Latence live maîtrisée** : rattrapage du direct activé dans mpegts.js (profil rapide) — les micro-coupures ne font plus dériver la lecture derrière le direct
|
||||
- **Fix « Échec du chargement : vendor/mpegts.min.js »** : un échec de chargement d'une lib de lecture n'affiche plus un écran d'erreur définitif. Le chargement est retenté une fois en contournant le cache HTTP (une entrée tronquée condamnait le lecteur jusqu'au vidage manuel du cache), le résultat n'est mémorisé qu'en cas de succès (une promesse rejetée en cache rendait tout réessai impossible) et, si la lib reste introuvable, le live bascule automatiquement sur la route HLS équivalente. Le message affiché précise désormais la cause (HTTP 404, 429, réseau injoignable)
|
||||
- **Préchargement de la bonne lib** : les trois players préchargeaient hls.js en dur, soit 618 Ko téléchargés pour rien à chaque zap TV — où c'est mpegts.js qui sert — au détriment du flux et du chargement de mpegts.js. Le préchargement suit maintenant le flux réellement demandé (et ne charge rien sur Safari/iOS, qui lit le HLS nativement)
|
||||
- **Alerte au démarrage** : le serveur signale explicitement l'absence de `web/vendor/*.min.js` au lancement, au lieu de laisser le navigateur échouer sans explication
|
||||
|
||||
### 🧰 Qualité / Infra
|
||||
- **Builds reproductibles** : `pubspec.lock` (frontend et backend) désormais versionnés et utilisés par le Dockerfile — chaque build résolvait jusqu'ici des versions fraîches
|
||||
- **CI durcie** : versions Flutter/Dart épinglées, cache pub, annulation des runs obsolètes (`concurrency`) ; `docker-publish` ne publie plus `:latest` qu'après une CI verte sur main (il tournait en parallèle et pouvait publier une image cassée)
|
||||
|
||||
@@ -94,7 +94,11 @@ List<String> _liveVideoArgs(String quality, bool gpu) {
|
||||
'-g', '50',
|
||||
]
|
||||
: [
|
||||
'-c:v', 'libx264', '-preset', 'medium', '-tune', 'zerolatency',
|
||||
// veryfast au lieu de medium : en live, l'encodeur doit tenir
|
||||
// le temps réel ET produire le premier segment vite ; medium
|
||||
// ajoutait plusieurs secondes au zap sans gain visible à ce
|
||||
// débit.
|
||||
'-c:v', 'libx264', '-preset', 'veryfast', '-tune', 'zerolatency',
|
||||
'-profile:v', 'high', '-level', '4.0',
|
||||
'-b:v', '6000k', '-maxrate', '8000k', '-bufsize', '12000k',
|
||||
'-pix_fmt', 'yuv420p', '-g', '50',
|
||||
@@ -318,6 +322,11 @@ Handler createLiveStreamHandler(
|
||||
// Abort reads stuck for 30s so a stalled upstream triggers the
|
||||
// reconnect logic instead of wedging the process forever.
|
||||
'-rw_timeout', '30000000',
|
||||
// Démarrage rapide : sans borne, FFmpeg peut passer plusieurs
|
||||
// secondes à sonder le flux avant d'écrire le premier segment.
|
||||
'-fflags', 'nobuffer',
|
||||
'-probesize', '1000000',
|
||||
'-analyzeduration', '1000000',
|
||||
'-i', targetUrl,
|
||||
..._liveVideoArgs(quality, useNvidiaGpu),
|
||||
..._audioArgs(withFilters: false),
|
||||
@@ -364,6 +373,85 @@ Handler createLiveStreamHandler(
|
||||
return Response.found('/api/live/$streamId/$quality/playlist.m3u8');
|
||||
});
|
||||
|
||||
// Route: /api/live/{streamId}/turbo.ts — flux MPEG-TS continu pour le
|
||||
// player web (mpegts.js) : vidéo copiée telle quelle, audio TOUJOURS
|
||||
// réencodé en AAC.
|
||||
//
|
||||
// POURQUOI : mpegts.js ne démuxe que l'AAC et le MP3. Les chaînes qui
|
||||
// diffusent en AC-3/E-AC-3 (0x81/0x87) ou en MPEG-1 Layer II passaient par
|
||||
// le proxy brut → image sans aucun son. Le réencodage audio seul coûte
|
||||
// quelques % de CPU (pas de transcodage vidéo) et garde le zapping
|
||||
// instantané : un seul flux continu, pas de segmentation HLS à amorcer.
|
||||
//
|
||||
// Latence : -fflags nobuffer + probesize réduit → première image en
|
||||
// ~0,5-1,5 s au lieu des 2-6 s d'analyse par défaut de FFmpeg.
|
||||
router.get('/<streamId>/turbo.ts', (Request request, String streamId) async {
|
||||
if (!_isValidStreamId(streamId)) {
|
||||
return Response.badRequest(body: 'Invalid stream ID');
|
||||
}
|
||||
final playlist = await getPlaylist(request);
|
||||
if (playlist == null) return Response.forbidden('No playlist');
|
||||
|
||||
final targetUrl =
|
||||
'${playlist.dns}/live/${playlist.username}/${playlist.password}/$streamId.ts';
|
||||
print(
|
||||
'[Live Turbo] $streamId: ${LogRedactor.redactUrl(targetUrl)}',
|
||||
);
|
||||
|
||||
final process = await Process.start(_getFFmpegPath(), [
|
||||
'-hide_banner', '-loglevel', 'warning',
|
||||
'-headers', 'User-Agent: VLC/3.0.18 LibVLC/3.0.18\r\n',
|
||||
'-reconnect', '1', '-reconnect_streamed', '1',
|
||||
'-reconnect_at_eof', '1',
|
||||
'-reconnect_delay_max', '10',
|
||||
'-rw_timeout', '30000000',
|
||||
// Démarrage rapide : ne pas bufferiser l'analyse, sonde réduite.
|
||||
'-fflags', 'nobuffer',
|
||||
'-flags', 'low_delay',
|
||||
'-probesize', '1000000',
|
||||
'-analyzeduration', '1000000',
|
||||
'-i', targetUrl,
|
||||
'-c:v', 'copy',
|
||||
'-c:a', 'aac', '-b:a', '160k', '-ac', '2', '-ar', '48000',
|
||||
'-af', 'aresample=async=1',
|
||||
// Pas de délai de mux : les paquets partent dès qu'ils existent.
|
||||
'-muxdelay', '0', '-muxpreload', '0',
|
||||
'-f', 'mpegts', 'pipe:1',
|
||||
]);
|
||||
|
||||
// Journaliser les erreurs FFmpeg (redactées) sans bloquer le flux.
|
||||
process.stderr.transform(const SystemEncoding().decoder).listen((line) {
|
||||
final trimmed = line.trim();
|
||||
if (trimmed.isNotEmpty) {
|
||||
print('[Live Turbo] $streamId ffmpeg: '
|
||||
'${LogRedactor.redactUrl(trimmed)}');
|
||||
}
|
||||
});
|
||||
|
||||
// Relayer stdout vers le client ; tuer FFmpeg dès que le client zappe
|
||||
// ou ferme l'onglet (sinon les processus s'accumulent à chaque zap).
|
||||
final controller = StreamController<List<int>>();
|
||||
final subscription = process.stdout.listen(
|
||||
controller.add,
|
||||
onError: controller.addError,
|
||||
onDone: controller.close,
|
||||
);
|
||||
controller.onCancel = () {
|
||||
subscription.cancel();
|
||||
process.kill(ProcessSignal.sigterm);
|
||||
};
|
||||
|
||||
return Response(
|
||||
200,
|
||||
body: controller.stream,
|
||||
headers: {
|
||||
'Content-Type': 'video/mp2t',
|
||||
'Cache-Control': 'no-store',
|
||||
'Connection': 'keep-alive',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
// Route: /api/live/{streamId}.ts (Direct Proxy for recordings/raw playback)
|
||||
router.get('/<streamId>.ts', (Request request, String streamId) async {
|
||||
final playlist = await getPlaylist(request);
|
||||
@@ -464,8 +552,11 @@ Handler createVodStreamHandler(
|
||||
'-reconnect_delay_max', '10',
|
||||
'-rw_timeout', '30000000',
|
||||
'-timeout', '30000000',
|
||||
'-analyzeduration', '5000000',
|
||||
'-probesize', '10000000',
|
||||
// Sonde réduite (10 Mo → 5 Mo) : sur un upstream lent, télécharger
|
||||
// 10 Mo avant la première image ajoutait plusieurs secondes au
|
||||
// démarrage de chaque film.
|
||||
'-analyzeduration', '2000000',
|
||||
'-probesize', '5000000',
|
||||
'-i', targetUrl,
|
||||
..._vodVideoArgs(quality, useNvidiaGpu),
|
||||
..._audioArgs(withFilters: quality != 'source'),
|
||||
@@ -586,7 +677,11 @@ Handler createRecordingStreamHandler(
|
||||
'-bufsize', '6000k',
|
||||
'-g', '48', '-bf', '2', '-pix_fmt', 'yuv420p',
|
||||
] else ...[
|
||||
'-c:v', 'libx264', '-preset', 'medium', '-crf', '18',
|
||||
// veryfast/crf 20 au lieu de medium/crf 18 : à ce niveau le rendu
|
||||
// est visuellement identique, mais medium ne tenait pas le temps
|
||||
// réel en 1080p sur un CPU modeste → lecture d'enregistrement qui
|
||||
// démarre lentement puis bufferise.
|
||||
'-c:v', 'libx264', '-preset', 'veryfast', '-crf', '20',
|
||||
'-maxrate', '12000k', '-bufsize', '24000k', '-pix_fmt', 'yuv420p',
|
||||
'-g', '48', '-threads', '0',
|
||||
],
|
||||
|
||||
+15
-1
@@ -259,6 +259,20 @@ void main(List<String> args) async {
|
||||
}),
|
||||
);
|
||||
|
||||
// Les libs de lecture sont servies depuis l'image, plus depuis un CDN : si
|
||||
// elles manquent (build web incomplet, copie Docker partielle), le lecteur
|
||||
// échoue côté navigateur avec un simple « Échec du chargement » sans que
|
||||
// rien ne l'ait signalé au démarrage. On le dit ici, une fois, clairement.
|
||||
for (final lib in const ['hls.min.js', 'mpegts.min.js']) {
|
||||
final file = File('$webPath/vendor/$lib');
|
||||
if (!file.existsSync()) {
|
||||
print(
|
||||
'[Server] ATTENTION: web/vendor/$lib absent de $webPath — '
|
||||
'la lecture échouera dans le navigateur.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Create static handler
|
||||
final baseStaticHandler = createStaticHandler(
|
||||
webPath,
|
||||
@@ -277,7 +291,7 @@ void main(List<String> args) async {
|
||||
final isVendored = path.startsWith('vendor/');
|
||||
if (!isVendored &&
|
||||
(path.isEmpty ||
|
||||
path == 'index.html' ||
|
||||
path.endsWith('.html') ||
|
||||
path.endsWith('.js') ||
|
||||
path.endsWith('.json'))) {
|
||||
return response.change(
|
||||
|
||||
@@ -165,7 +165,9 @@ class FfmpegSessionManager {
|
||||
'${session.recentStderr.join().trim()}'
|
||||
);
|
||||
}
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
// 100 ms : à 500 ms, on ajoutait en moyenne un quart de seconde de
|
||||
// latence pure entre la disponibilité de la playlist et sa réponse.
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
}
|
||||
return (ready: false, error: 'Timeout waiting for transcoder');
|
||||
}
|
||||
|
||||
@@ -190,18 +190,17 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
|
||||
// - Live TV: Player Lite (simple TS playback with mpegts.js)
|
||||
// - VOD/Series: Player Standard (fuller controls, HLS support)
|
||||
|
||||
// Cache buster to force reload of updated player.html
|
||||
final cacheBuster = DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
final streamTypeParam =
|
||||
widget.streamType == StreamType.live ? 'live' : 'vod';
|
||||
final playerFile = isMobile
|
||||
? 'player_mobile.html'
|
||||
: (isLiveTV ? 'player_lite.html' : 'player.html');
|
||||
|
||||
// Inject Turbo-Start flag
|
||||
// Plus de cache-buster « &v=timestamp » : il forçait le re-téléchargement
|
||||
// et le re-parse de player.html à CHAQUE zap. Le serveur sert désormais
|
||||
// les .html en no-cache, la fraîcheur est garantie sans pénaliser le zap.
|
||||
var playerSrc =
|
||||
'$playerFile?url=$encodedUrl&type=$streamTypeParam&turbo=true&v=$cacheBuster';
|
||||
'$playerFile?url=$encodedUrl&type=$streamTypeParam&turbo=true';
|
||||
|
||||
if (widget.streamType == StreamType.recording) {
|
||||
playerSrc += '&is_recording=true';
|
||||
|
||||
@@ -176,8 +176,11 @@ class XtreamService {
|
||||
/// Faster zapping on compatible players (mpegts.js)
|
||||
String getLiveStreamUrlTs(String streamId) {
|
||||
if (_currentPlaylist == null) throw Exception('No playlist configured');
|
||||
// Backend route injects the Xtream credentials server-side
|
||||
return '$_backendBaseUrl/api/live/$streamId.ts';
|
||||
// Route « turbo » : vidéo copiée, audio réencodé en AAC côté serveur.
|
||||
// Le proxy brut ($_backendBaseUrl/api/live/$streamId.ts) livrait l'audio
|
||||
// d'origine — AC-3/E-AC-3/MP2 que mpegts.js ne décode pas → chaînes
|
||||
// muettes. Il reste utilisé tel quel par le scheduler d'enregistrement.
|
||||
return '$_backendBaseUrl/api/live/$streamId/turbo.ts';
|
||||
}
|
||||
|
||||
/// Generate stream URL for VOD (movies)
|
||||
|
||||
+29
-1
@@ -11,7 +11,35 @@
|
||||
et environ 200 Ko de JS jamais téléchargés dans le cas courant.
|
||||
-->
|
||||
<link rel="stylesheet" href="xf-player.css">
|
||||
<link rel="preload" href="vendor/hls.min.js" as="script">
|
||||
<script>
|
||||
// Précharge la SEULE lib utile à CE flux, dès le parse du <head>.
|
||||
// Un préchargement fixe de hls.js faisait télécharger 618 Ko inutiles
|
||||
// à chaque zap TV — la lib réellement nécessaire au direct est
|
||||
// mpegts.js — et cette bande passante était prise sur le flux
|
||||
// lui-même et sur mpegts.js, jusqu'à faire échouer son chargement sur
|
||||
// les liens contraints. Même décision que XFPlayer.start().
|
||||
(function () {
|
||||
var p = new URLSearchParams(location.search);
|
||||
var url = (p.get('url') || '').toLowerCase();
|
||||
var isHls = url.indexOf('.m3u8') !== -1;
|
||||
var nativeHls =
|
||||
document.createElement('video')
|
||||
.canPlayType('application/vnd.apple.mpegurl') !== '';
|
||||
var lib = null;
|
||||
if (isHls) {
|
||||
// Safari/iOS lit le HLS nativement : aucune lib à charger.
|
||||
if (!nativeHls) lib = 'hls.min.js';
|
||||
} else if (p.get('type') === 'live' || url.indexOf('.ts') !== -1) {
|
||||
lib = 'mpegts.min.js';
|
||||
}
|
||||
if (!lib) return;
|
||||
var l = document.createElement('link');
|
||||
l.rel = 'preload';
|
||||
l.as = 'script';
|
||||
l.href = 'vendor/' + lib;
|
||||
document.head.appendChild(l);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
+29
-1
@@ -5,7 +5,35 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>XtremFlow Player Lite</title>
|
||||
<link rel="stylesheet" href="xf-player.css">
|
||||
<link rel="preload" href="vendor/hls.min.js" as="script">
|
||||
<script>
|
||||
// Précharge la SEULE lib utile à CE flux, dès le parse du <head>.
|
||||
// Un préchargement fixe de hls.js faisait télécharger 618 Ko inutiles
|
||||
// à chaque zap TV — la lib réellement nécessaire au direct est
|
||||
// mpegts.js — et cette bande passante était prise sur le flux
|
||||
// lui-même et sur mpegts.js, jusqu'à faire échouer son chargement sur
|
||||
// les liens contraints. Même décision que XFPlayer.start().
|
||||
(function () {
|
||||
var p = new URLSearchParams(location.search);
|
||||
var url = (p.get('url') || '').toLowerCase();
|
||||
var isHls = url.indexOf('.m3u8') !== -1;
|
||||
var nativeHls =
|
||||
document.createElement('video')
|
||||
.canPlayType('application/vnd.apple.mpegurl') !== '';
|
||||
var lib = null;
|
||||
if (isHls) {
|
||||
// Safari/iOS lit le HLS nativement : aucune lib à charger.
|
||||
if (!nativeHls) lib = 'hls.min.js';
|
||||
} else if (p.get('type') === 'live' || url.indexOf('.ts') !== -1) {
|
||||
lib = 'mpegts.min.js';
|
||||
}
|
||||
if (!lib) return;
|
||||
var l = document.createElement('link');
|
||||
l.rel = 'preload';
|
||||
l.as = 'script';
|
||||
l.href = 'vendor/' + lib;
|
||||
document.head.appendChild(l);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
+29
-1
@@ -8,7 +8,35 @@
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<title>XtremFlow Player Mobile</title>
|
||||
<link rel="stylesheet" href="xf-player.css">
|
||||
<link rel="preload" href="vendor/hls.min.js" as="script">
|
||||
<script>
|
||||
// Précharge la SEULE lib utile à CE flux, dès le parse du <head>.
|
||||
// Un préchargement fixe de hls.js faisait télécharger 618 Ko inutiles
|
||||
// à chaque zap TV — la lib réellement nécessaire au direct est
|
||||
// mpegts.js — et cette bande passante était prise sur le flux
|
||||
// lui-même et sur mpegts.js, jusqu'à faire échouer son chargement sur
|
||||
// les liens contraints. Même décision que XFPlayer.start().
|
||||
(function () {
|
||||
var p = new URLSearchParams(location.search);
|
||||
var url = (p.get('url') || '').toLowerCase();
|
||||
var isHls = url.indexOf('.m3u8') !== -1;
|
||||
var nativeHls =
|
||||
document.createElement('video')
|
||||
.canPlayType('application/vnd.apple.mpegurl') !== '';
|
||||
var lib = null;
|
||||
if (isHls) {
|
||||
// Safari/iOS lit le HLS nativement : aucune lib à charger.
|
||||
if (!nativeHls) lib = 'hls.min.js';
|
||||
} else if (p.get('type') === 'live' || url.indexOf('.ts') !== -1) {
|
||||
lib = 'mpegts.min.js';
|
||||
}
|
||||
if (!lib) return;
|
||||
var l = document.createElement('link');
|
||||
l.rel = 'preload';
|
||||
l.as = 'script';
|
||||
l.href = 'vendor/' + lib;
|
||||
document.head.appendChild(l);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
Vendored
+3
-1
@@ -1,2 +1,4 @@
|
||||
!function e(t){var r,i;r=this,i=function(){"use strict";function r(e,t){for(var r=0;r<t.length;r++){var i=t[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,f(i.key),i)}}function i(e,t,i){return t&&r(e.prototype,t),i&&r(e,i),Object.defineProperty(e,"prototype",{writable:!1}),e}function n(e,t,r){return(t=f(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(){return a=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var i in r)({}).hasOwnProperty.call(r,i)&&(e[i]=r[i])}return e},a.apply(null,arguments)}function s(e){return s=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},s(e)}function o(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,h(e,t)}function l(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(l=function(){return!!e})()}function u(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,i)}return r}function d(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?u(Object(r),!0).forEach((function(t){n(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):u(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function h(e,t){return h=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},h(e,t)}function f(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var i=r.call(e,t);if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}function c(e){var t="function"==typeof Map?new Map:void 0;return c=function(e){if(null===e||!function(e){try{return-1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return function(e,t,r){if(l())return Reflect.construct.apply(null,arguments);var i=[null];i.push.apply(i,t);var n=new(e.bind.apply(e,i));return r&&h(n,r.prototype),n}(e,arguments,s(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),h(r,e)},c(e)}function g(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var v,m,p={exports:{}},y=(v||(v=1,function(e){var t=Object.prototype.hasOwnProperty,r="~";function i(){}function n(e,t,r){this.fn=e,this.context=t,this.once=r||!1}function a(e,t,i,a,s){if("function"!=typeof i)throw new TypeError("The listener must be a function");var o=new n(i,a||e,s),l=r?r+t:t;return e._events[l]?e._events[l].fn?e._events[l]=[e._events[l],o]:e._events[l].push(o):(e._events[l]=o,e._eventsCount++),e}function s(e,t){0==--e._eventsCount?e._events=new i:delete e._events[t]}function o(){this._events=new i,this._eventsCount=0}Object.create&&(i.prototype=Object.create(null),(new i).__proto__||(r=!1)),o.prototype.eventNames=function(){var e,i,n=[];if(0===this._eventsCount)return n;for(i in e=this._events)t.call(e,i)&&n.push(r?i.slice(1):i);return Object.getOwnPropertySymbols?n.concat(Object.getOwnPropertySymbols(e)):n},o.prototype.listeners=function(e){var t=r?r+e:e,i=this._events[t];if(!i)return[];if(i.fn)return[i.fn];for(var n=0,a=i.length,s=new Array(a);n<a;n++)s[n]=i[n].fn;return s},o.prototype.listenerCount=function(e){var t=r?r+e:e,i=this._events[t];return i?i.fn?1:i.length:0},o.prototype.emit=function(e,t,i,n,a,s){var o=r?r+e:e;if(!this._events[o])return!1;var l,u,d=this._events[o],h=arguments.length;if(d.fn){switch(d.once&&this.removeListener(e,d.fn,void 0,!0),h){case 1:return d.fn.call(d.context),!0;case 2:return d.fn.call(d.context,t),!0;case 3:return d.fn.call(d.context,t,i),!0;case 4:return d.fn.call(d.context,t,i,n),!0;case 5:return d.fn.call(d.context,t,i,n,a),!0;case 6:return d.fn.call(d.context,t,i,n,a,s),!0}for(u=1,l=new Array(h-1);u<h;u++)l[u-1]=arguments[u];d.fn.apply(d.context,l)}else{var f,c=d.length;for(u=0;u<c;u++)switch(d[u].once&&this.removeListener(e,d[u].fn,void 0,!0),h){case 1:d[u].fn.call(d[u].context);break;case 2:d[u].fn.call(d[u].context,t);break;case 3:d[u].fn.call(d[u].context,t,i);break;case 4:d[u].fn.call(d[u].context,t,i,n);break;default:if(!l)for(f=1,l=new Array(h-1);f<h;f++)l[f-1]=arguments[f];d[u].fn.apply(d[u].context,l)}}return!0},o.prototype.on=function(e,t,r){return a(this,e,t,r,!1)},o.prototype.once=function(e,t,r){return a(this,e,t,r,!0)},o.protLine truncated
|
||||
!function e(t){var r,i;r=this,i=function(){"use strict";function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,i=Array(t);r<t;r++)i[r]=e[r];return i}function i(e,t,r,i,n,a,s){try{var o=e[a](s),l=o.value}catch(e){return void r(e)}o.done?t(l):Promise.resolve(l).then(i,n)}function n(e,t){for(var r=0;r<t.length;r++){var i=t[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,y(i.key),i)}}function a(e,t,r){return t&&n(e.prototype,t),r&&n(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e}function s(e,t){var i="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(i)return(i=i.call(e)).next.bind(i);if(Array.isArray(e)||(i=function(e,t){if(e){if("string"==typeof e)return r(e,t);var i={}.toString.call(e).slice(8,-1);return"Object"===i&&e.constructor&&(i=e.constructor.name),"Map"===i||"Set"===i?Array.from(e):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?r(e,t):void 0}}(e))||t){i&&(e=i);var n=0;return function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function o(e,t,r){return(t=y(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(){return l=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var i in r)({}).hasOwnProperty.call(r,i)&&(e[i]=r[i])}return e},l.apply(null,arguments)}function u(e){return u=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},u(e)}function d(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,p(e,t)}function h(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(h=function(){return!!e})()}function f(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,i)}return r}function c(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?f(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):f(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function g(e,t){if(null==e)return{};var r={};for(var i in e)if({}.hasOwnProperty.call(e,i)){if(-1!==t.indexOf(i))continue;r[i]=e[i]}return r}function v(){
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
|
||||
var e,t,r="function"==typeof Symbol?Symbol:{},i=r.iterator||"@@iterator",n=r.toStringTag||"@@toStringTag";function a(r,i,n,a){var l=i&&i.prototype instanceof o?i:o,u=Object.create(l.prototype);return m(u,"_invoke",function(r,i,n){var a,o,l,u=0,d=n||[],h=!1,f={p:0,n:0,v:e,a:c,f:c.bind(e,4),d:function(t,r){return a=t,o=0,l=e,f.n=r,s}};function c(r,i){for(o=r,l=i,t=0;!h&&u&&!n&&t<d.length;t++){var n,a=d[t],c=f.p,g=a[2];r>3?(n=g===i)&&(l=a[(o=a[4])?5:(o=3,3)],a[4]=a[5]=e):a[0]<=c&&((n=r<2&&c<a[1])?(o=0,f.v=i,f.n=a[1]):c<g&&(n=r<3||a[0]>i||i>g)&&(a[4]=r,a[5]=i,f.n=g,o=0))}if(n||r>1)return s;throw h=!0,i}return function(n,d,g){if(u>1)throw TypeError("Generator is already running");for(h&&1===d&&c(d,g),o=d,l=g;(t=o<2?e:l)||!h;){a||(o?o<3?(o>1&&(f.n=-1),c(o,l)):f.n=l:f.v=l);try{if(u=2,a){if(o||(n="next"),t=a[n]){if(!(t=t.call(a,l)))throw TypeError("iterator result is not an object");if(!t.done)return t;l=t.value,o<2&&(o=0)}else 1===o&&(t=a.return)&&t.call(a),o<2&&(l=TypeError("The iterator does not provide a '"+n+"' method"),o=1);a=e}else if((t=(h=f.n<0)?l:r.call(i,f))!==s)break}catch(t){a=e,o=1,l=t}finally{u=1}}return{value:t,done:h}}}(r,n,a),!0),u}var s={};function o(){}function l(){}function u(){}t=Object.getPrototypeOf;var d=[][i]?t(t([][i]())):(m(t={},i,(function(){return this})),t),h=u.prototype=o.prototype=Object.create(d);function f(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,u):(e.__proto__=u,m(e,n,"GeneratorFunction")),e.prototype=Object.create(h),e}return l.prototype=u,m(h,"constructor",u),m(u,"constructor",l),l.displayName="GeneratorFunction",m(u,n,"GeneratorFunction"),m(h),m(h,n,"Generator"),m(h,i,(function(){return this})),m(h,"toString",(function(){return"[object Generator]"})),(v=function(){return{w:a,m:f}})()}function m(e,t,r,i){var n=Object.defineProperty;try{n({},"",{})}catch(e){n=0}m=function(e,t,r,i){function a(t,r){m(e,t,(function(e){return this._invoke(t,r,e)}))}t?n?n(e,t,{value:r,enumerable:!i,configurable:!i,writable:!i}):e[t]=r:(a("next",0),a("throw",1),a("return",2))},m(e,t,r,i)}function p(e,t){return p=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},p(e,t)}function y(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var i=r.call(e,t);if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}function E(e){var t="function"==typeof Map?new Map:void 0;return E=function(e){if(null===e||!function(e){try{return-1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return function(e,t,r){if(h())return Reflect.construct.apply(null,arguments);var i=[null];i.push.apply(i,t);var n=new(e.bind.apply(e,i));return r&&p(n,r.prototype),n}(e,arguments,u(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),p(r,e)},E(e)}function T(e){return e instanceof ArrayBuffer||"undefined"!=typeof SharedArrayBuffer&&e instanceof SharedArrayBuffer}var S="utf-16",A="utf-16be",I="utf-16le",L="utf-8";function R(e,t){if(e<0)return-R(-e,t);var r=Math.pow(10,t);if(Math.abs(e*r%1-.5)<Number.EPSILON){var i=Math.floor(e*r);return(i%2==0?i:i+1)/r}return Math.round(e*r)/r}function b(){try{return crypto.randomUUID()}catch(i){try{var e=URL.createObjectURL(new Blob),t=e.toString();return URL.revokeObjectURL(e),t.slice(t.lastIndexOf("/")+1)}catch(e){var r=(new Date).getTime();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(e){var t=(r+16*Math.random())%16|0;return r=Math.floor(r/16),("x"==e?t:3&t|8).toString(16)}))}}}function k(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var D,P,_={exports:{}},C=(D||(D=1,function(e){var t=Object.prototype.hasOwnProperty,r="~";function i(){}function n(e,t,r){this.fn=e,this.context=t,this.once=r||!1}function a(e,t,i,a,s){if("function"!=typeof i)throw new TypeError("The listener must be a function");var o=new n(i,a||e,s),l=r?r+t:t;return e._events[l]?e._events[l].fn?e._events[l]=[e._events[l],o]:e._events[l].push(o):(e._events[l]=o,e._eventsCount++),e}function s(e,t){0==--e._eventsCount?e._events=new i:delete e._events[t]}function o(){this._events=new i,this._eventsCount=0}Object.create&&(i.prototype=Object.create(null),(new i).__proto__||(r=!1)),o.prototype.eventNames=function(){var e,i,n=[];if(0===this._eventsCount)return n;for(i in e=this._events)t.call(e,i)&&n.push(r?i.slice(1):i);return Object.getOwnPropertySymbols?n.concat(Object.getOwnPropertySymbols(e)):n},o.prototype.listeners=function(e){var t=r?r+e:e,i=this._events[t];if(!i)return[];if(i.fn)return[i.fn];for(var n=0,a=i.length,s=new Array(a);n<a;n++)s[n]=i[n].fn;retLine truncated
|
||||
//# sourceMappingURL=hls.min.js.map
|
||||
Vendored
+2
-8
@@ -1,9 +1,3 @@
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.mpegts=t():e.mpegts=t()}(window,(function(){return function(e){var t={};function i(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return e[n].call(a.exports,a,a.exports,i),a.l=!0,a.exports}return i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)i.d(n,a,function(t){return e[t]}.bind(null,a));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=14)}([function(e,t,i){"use strict";var n=i(6),a=i.n(n),r=function(){function e(){}return e.e=function(t,i){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var n="["+t+"] > "+i;e.ENABLE_CALLBACK&&e.emitter.emit("log","error",n),e.ENABLE_ERROR&&(console.error?console.error(n):console.warn?console.warn(n):console.log(n))},e.i=function(t,i){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var n="["+t+"] > "+i;e.ENABLE_CALLBACK&&e.emitter.emit("log","info",n),e.ENABLE_INFO&&(console.info?console.info(n):console.log(n))},e.w=function(t,i){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var n="["+t+"] > "+i;e.ENABLE_CALLBACK&&e.emitter.emit("log","warn",n),e.ENABLE_WARN&&(console.warn?console.warn(n):console.log(n))},e.d=function(t,i){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var n="["+t+"] > "+i;e.ENABLE_CALLBACK&&e.emitter.emit("log","debug",n),e.ENABLE_DEBUG&&(console.debug?console.debug(n):console.log(n))},e.v=function(t,i){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var n="["+t+"] > "+i;e.ENABLE_CALLBACK&&e.emitter.emit("log","verbose",n),e.ENABLE_VERBOSE&&console.log(n)},e}();r.GLOBAL_TAG="mpegts.js",r.FORCE_GLOBAL_TAG=!1,r.ENABLE_ERROR=!0,r.ENABLE_INFO=!0,r.ENABLE_WARN=!0,r.ENABLE_DEBUG=!0,r.ENABLE_VERBOSE=!0,r.ENABLE_CALLBACK=!1,r.emitter=new a.a,t.a=r},function(e,t,i){"use strict";t.a={IO_ERROR:"io_error",DEMUX_ERROR:"demux_error",INIT_SEGMENT:"init_segment",MEDIA_SEGMENT:"media_segment",LOADING_COMPLETE:"loading_complete",RECOVERED_EARLY_EOF:"recovered_early_eof",MEDIA_INFO:"media_info",METADATA_ARRIVED:"metadata_arrived",SCRIPTDATA_ARRIVED:"scriptdata_arrived",TIMED_ID3_METADATA_ARRIVED:"timed_id3_metadata_arrived",SMPTE2038_METADATA_ARRIVED:"smpte2038_metadata_arrived",SCTE35_METADATA_ARRIVED:"scte35_metadata_arrived",PES_PRIVATE_DATA_DESCRIPTOR:"pes_private_data_descriptor",PES_PRIVATE_DATA_ARRIVED:"pes_private_data_arrived",STATISTICS_INFO:"statistics_info",RECOMMEND_SEEKPOINT:"recommend_seekpoint"}},function(e,t,i){"use strict";i.d(t,"c",(function(){return a})),i.d(t,"b",(function(){return r})),i.d(t,"a",(function(){return s}));var n=i(3),a={kIdle:0,kConnecting:1,kBuffering:2,kError:3,kComplete:4},r={OK:"OK",EXCEPTION:"Exception",HTTP_STATUS_CODE_INVALID:"HttpStatusCodeInvalid",CONNECTING_TIMEOUT:"ConnectingTimeout",EARLY_EOF:"EarlyEof",UNRECOVERABLE_EARLY_EOF:"UnrecoverableEarlyEof"},s=function(){function e(e){this._type=e||"undefined",this._status=a.kIdle,this._needStash=!1,this._onContentLengthKnown=null,this._onURLRedirect=null,this._onDataArrival=null,this._onError=null,this._onComplete=null}return e.prototype.destroy=function(){this._status=a.kIdle,this._onContentLengthKnown=null,this._onURLRedirect=null,this._onDataArrival=null,this._onError=null,this._onComplete=null},e.prototype.isWorking=function(){return this._status===a.kConnecting||this._status===a.kBuffering},Object.defineProperty(e.prototype,"type",{get:function(){return this._type},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"status",{get:function(){return this._status},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"needStashBuffer",{get:function(){return this._needStash},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"onContentLengthKnown",{get:function(){return this._onContentLengthKnown},set:function(e){this._onContentLengthKnown=e},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"onURLRedirect",{get:function(){return this._onURLRedirect},set:function(e){this._onURLRedirect=e},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"onDataArrival",{get:function(){return this._onDataArrival},set:function(e){this._onDataArrival=e},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"onError",{get:function(){return this._onError},set:function(e){this._onError=e},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"onComplete",{get:fuLine truncated
|
||||
/*!
|
||||
* @overview es6-promise - a tiny implementation of Promises/A+.
|
||||
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
|
||||
* @license Licensed under MIT license
|
||||
* See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
|
||||
* @version v4.2.8+1e68dce6
|
||||
*/var n;n=function(){"use strict";function e(e){return"function"==typeof e}var n=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},a=0,r=void 0,s=void 0,o=function(e,t){f[a]=e,f[a+1]=t,2===(a+=2)&&(s?s(p):b())},d="undefined"!=typeof window?window:void 0,_=d||{},h=_.MutationObserver||_.WebKitMutationObserver,c="undefined"==typeof self&&void 0!==t&&"[object process]"==={}.toString.call(t),u="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel;function l(){var e=setTimeout;return function(){return e(p,1)}}var f=new Array(1e3);function p(){for(var e=0;e<a;e+=2)(0,f[e])(f[e+1]),f[e]=void 0,f[e+1]=void 0;a=0}var m,g,v,y,b=void 0;function S(e,t){var i=this,n=new this.constructor(R);void 0===n[A]&&P(n);var a=i._state;if(a){var r=arguments[a-1];o((function(){return I(a,n,r,i._result)}))}else C(i,n,e,t);return n}function E(e){if(e&&"object"==typeof e&&e.constructor===this)return e;var t=new this(R);return L(t,e),t}c?b=function(){return t.nextTick(p)}:h?(g=0,v=new h(p),y=document.createTextNode(""),v.observe(y,{characterData:!0}),b=function(){y.data=g=++g%2}):u?((m=new MessageChannel).port1.onmessage=p,b=function(){return m.port2.postMessage(0)}):b=void 0===d?function(){try{var e=Function("return this")().require("vertx");return void 0!==(r=e.runOnLoop||e.runOnContext)?function(){r(p)}:l()}catch(e){return l()}}():l();var A=Math.random().toString(36).substring(2);function R(){}function T(t,i,n){i.constructor===t.constructor&&n===S&&i.constructor.resolve===E?function(e,t){1===t._state?k(e,t._result):2===t._state?D(e,t._result):C(t,void 0,(function(t){return L(e,t)}),(function(t){return D(e,t)}))}(t,i):void 0===n?k(t,i):e(n)?function(e,t,i){o((function(e){var n=!1,a=function(e,t,i,n){try{e.call(t,i,n)}catch(e){return e}}(i,t,(function(i){n||(n=!0,t!==i?L(e,i):k(e,i))}),(function(t){n||(n=!0,D(e,t))}),e._label);!n&&a&&(n=!0,D(e,a))}),e)}(t,i,n):k(t,i)}function L(e,t){if(e===t)D(e,new TypeError("You cannot resolve a promise with itself"));else if(a=typeof(n=t),null===n||"object"!==a&&"function"!==a)k(e,t);else{var i=void 0;try{i=t.then}catch(t){return void D(e,t)}T(e,t,i)}var n,a}function w(e){e._onerror&&e._onerror(e._result),B(e)}function k(e,t){void 0===e._state&&(e._result=t,e._state=1,0!==e._subscribers.length&&o(B,e))}function D(e,t){void 0===e._state&&(e._state=2,e._result=t,o(w,e))}function C(e,t,i,n){var a=e._subscribers,r=a.length;e._onerror=null,a[r]=t,a[r+1]=i,a[r+2]=n,0===r&&e._state&&o(B,e)}function B(e){var t=e._subscribers,i=e._state;if(0!==t.length){for(var n=void 0,a=void 0,r=e._result,s=0;s<t.length;s+=3)n=t[s],a=t[s+i],n?I(i,n,a,r):a(r);e._subscribers.length=0}}function I(t,i,n,a){var r=e(n),s=void 0,o=void 0,d=!0;if(r){try{s=n(a)}catch(e){d=!1,o=e}if(i===s)return void D(i,new TypeError("A promises callback cannot return that same promise."))}else s=a;void 0!==i._state||(r&&d?L(i,s):!1===d?D(i,o):1===t?k(i,s):2===t&&D(i,s))}var O=0;function P(e){e[A]=O++,e._state=void 0,e._result=void 0,e._subscribers=[]}var M=function(){function e(e,t){this._instanceConstructor=e,this.promise=new e(R),this.promise[A]||P(this.promise),n(t)?(this.length=t.length,this._remaining=t.length,this._result=new Array(this.length),0===this.length?k(this.promise,this._result):(this.length=this.length||0,this._enumerate(t),0===this._remaining&&k(this.promise,this._result))):D(this.promise,new Error("Array Methods must be provided an Array"))}return e.prototype._enumerate=function(e){for(var t=0;void 0===this._state&&t<e.length;t++)this._eachEntry(e[t],t)},e.prototype._eachEntry=function(e,t){var i=this._instanceConstructor,n=i.resolve;if(n===E){var a=void 0,r=void 0,s=!1;try{a=e.then}catch(e){s=!0,r=e}if(a===S&&void 0!==e._state)this._settledAt(e._state,t,e._result);else if("function"!=typeof a)this._remaining--,this._result[t]=e;else if(i===x){var o=new i(R);s?D(o,r):T(o,e,a),this._willSettleAt(o,t)}else this._willSettleAt(new i((function(t){return t(e)})),t)}else this._willSettleAt(n(e),t)},e.prototype._settledAt=function(e,t,i){var n=this.promise;void 0===n._state&&(this._remaining--,2===e?D(n,i):this._result[t]=i),0===this._remaining&&k(n,this._result)},e.prototype._willSettleAt=function(e,t){var i=this;C(e,void 0,(function(e){return i._settledAt(1,t,e)}),(function(e){return i._settledAt(2,t,e)}))},e}(),x=function(){function t(e){this[A]=O++,this._result=this._state=void 0,this._subscribers=[],R!==e&&("function"!=typeof e&&function(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}(),this instanceof t?function(e,t){try{t((function(t){L(e,t)}),(function(t){D(e,t)}))}catch(t){D(e,t)}}(this,e):function(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}())}return t.prototype.catch=function(e){return this.then(null,e)},t.prototype.finally=function(t){var i=this.constructor;returLine truncated
|
||||
/*! For license information please see mpegts.js.LICENSE.txt */
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.mpegts=t():e.mpegts=t()}(this,function(){return function(){var e={964:function(e,t,i){e.exports=function(){"use strict";function e(e){return"function"==typeof e}var t=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},a=0,n=void 0,r=void 0,o=function(e,t){h[a]=e,h[a+1]=t,2===(a+=2)&&(r?r(f):y())};var s="undefined"!=typeof window?window:void 0,d=s||{},_=d.MutationObserver||d.WebKitMutationObserver,l="undefined"==typeof self&&"undefined"!=typeof process&&"[object process]"==={}.toString.call(process),u="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel;function c(){var e=setTimeout;return function(){return e(f,1)}}var h=new Array(1e3);function f(){for(var e=0;e<a;e+=2)(0,h[e])(h[e+1]),h[e]=void 0,h[e+1]=void 0;a=0}var p,m,g,v,y=void 0;function S(e,t){var i=this,a=new this.constructor(b);void 0===a[A]&&x(a);var n=i._state;if(n){var r=arguments[n-1];o(function(){return O(n,a,r,i._result)})}else I(i,a,e,t);return a}function E(e){if(e&&"object"==typeof e&&e.constructor===this)return e;var t=new this(b);return D(t,e),t}y=l?function(){return process.nextTick(f)}:_?(m=0,g=new _(f),v=document.createTextNode(""),g.observe(v,{characterData:!0}),function(){v.data=m=++m%2}):u?((p=new MessageChannel).port1.onmessage=f,function(){return p.port2.postMessage(0)}):void 0===s?function(){try{var e=Function("return this")().require("vertx");return void 0!==(n=e.runOnLoop||e.runOnContext)?function(){n(f)}:c()}catch(e){return c()}}():c();var A=Math.random().toString(36).substring(2);function b(){}var R=void 0,T=1,L=2;function k(t,i,a){i.constructor===t.constructor&&a===S&&i.constructor.resolve===E?function(e,t){t._state===T?C(e,t._result):t._state===L?w(e,t._result):I(t,void 0,function(t){return D(e,t)},function(t){return w(e,t)})}(t,i):void 0===a?C(t,i):e(a)?function(e,t,i){o(function(e){var a=!1,n=function(e,t,i,a){try{e.call(t,i,a)}catch(e){return e}}(i,t,function(i){a||(a=!0,t!==i?D(e,i):C(e,i))},function(t){a||(a=!0,w(e,t))},e._label);!a&&n&&(a=!0,w(e,n))},e)}(t,i,a):C(t,i)}function D(e,t){if(e===t)w(e,new TypeError("You cannot resolve a promise with itself"));else if(n=typeof(a=t),null===a||"object"!==n&&"function"!==n)C(e,t);else{var i=void 0;try{i=t.then}catch(t){return void w(e,t)}k(e,t,i)}var a,n}function M(e){e._onerror&&e._onerror(e._result),B(e)}function C(e,t){e._state===R&&(e._result=t,e._state=T,0!==e._subscribers.length&&o(B,e))}function w(e,t){e._state===R&&(e._state=L,e._result=t,o(M,e))}function I(e,t,i,a){var n=e._subscribers,r=n.length;e._onerror=null,n[r]=t,n[r+T]=i,n[r+L]=a,0===r&&e._state&&o(B,e)}function B(e){var t=e._subscribers,i=e._state;if(0!==t.length){for(var a=void 0,n=void 0,r=e._result,o=0;o<t.length;o+=3)a=t[o],n=t[o+i],a?O(i,a,n,r):n(r);e._subscribers.length=0}}function O(t,i,a,n){var r=e(a),o=void 0,s=void 0,d=!0;if(r){try{o=a(n)}catch(e){d=!1,s=e}if(i===o)return void w(i,new TypeError("A promises callback cannot return that same promise."))}else o=n;i._state!==R||(r&&d?D(i,o):!1===d?w(i,s):t===T?C(i,o):t===L&&w(i,o))}var P=0;function x(e){e[A]=P++,e._state=void 0,e._result=void 0,e._subscribers=[]}var U=function(){function e(e,i){this._instanceConstructor=e,this.promise=new e(b),this.promise[A]||x(this.promise),t(i)?(this.length=i.length,this._remaining=i.length,this._result=new Array(this.length),0===this.length?C(this.promise,this._result):(this.length=this.length||0,this._enumerate(i),0===this._remaining&&C(this.promise,this._result))):w(this.promise,new Error("Array Methods must be provided an Array"))}return e.prototype._enumerate=function(e){for(var t=0;this._state===R&&t<e.length;t++)this._eachEntry(e[t],t)},e.prototype._eachEntry=function(e,t){var i=this._instanceConstructor,a=i.resolve;if(a===E){var n=void 0,r=void 0,o=!1;try{n=e.then}catch(e){o=!0,r=e}if(n===S&&e._state!==R)this._settledAt(e._state,t,e._result);else if("function"!=typeof n)this._remaining--,this._result[t]=e;else if(i===N){var s=new i(b);o?w(s,r):k(s,e,n),this._willSettleAt(s,t)}else this._willSettleAt(new i(function(t){return t(e)}),t)}else this._willSettleAt(a(e),t)},e.prototype._settledAt=function(e,t,i){var a=this.promise;a._state===R&&(this._remaining--,e===L?w(a,i):this._result[t]=i),0===this._remaining&&C(a,this._result)},e.prototype._willSettleAt=function(e,t){var i=this;I(e,void 0,function(e){return i._settledAt(T,t,e)},function(e){return i._settledAt(L,t,e)})},e}();var N=function(){function t(e){this[A]=P++,this._result=this._state=void 0,this._subscribers=[],b!==e&&("function"!=typeof e&&function(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}(),this instanceof t?function(e,t){try{t(function(t){D(e,t)},function(t){w(e,t)})}catch(t){w(e,t)}}(this,e):function(){throw new TypeELine truncated
|
||||
//# sourceMappingURL=mpegts.js.map
|
||||
+92
-11
@@ -60,17 +60,67 @@
|
||||
// ------------------------------------------------------------------
|
||||
var _scriptCache = {};
|
||||
|
||||
function loadScript(src) {
|
||||
if (_scriptCache[src]) return _scriptCache[src];
|
||||
_scriptCache[src] = new Promise(function (resolve, reject) {
|
||||
function _delay(ms) {
|
||||
return new Promise(function (resolve) { setTimeout(resolve, ms); });
|
||||
}
|
||||
|
||||
function _injectScript(src) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var s = document.createElement('script');
|
||||
s.src = src;
|
||||
s.async = true;
|
||||
s.onload = resolve;
|
||||
s.onerror = function () { reject(new Error('Échec du chargement : ' + src)); };
|
||||
s.onload = function () { resolve(); };
|
||||
s.onerror = function () {
|
||||
// Laisser une balise morte dans le <head> ferait échouer une
|
||||
// éventuelle nouvelle tentative sur le même src.
|
||||
if (s.parentNode) s.parentNode.removeChild(s);
|
||||
reject(new Error('script error'));
|
||||
};
|
||||
document.head.appendChild(s);
|
||||
});
|
||||
return _scriptCache[src];
|
||||
}
|
||||
|
||||
/**
|
||||
* Précise la cause d'un échec pour le message affiché et les logs :
|
||||
* 404 = lib absente de l'image déployée, 429 = quota du rate limiter,
|
||||
* échec réseau = lien coupé. Sans cela, toutes les causes se
|
||||
* ressemblaient à l'écran.
|
||||
*/
|
||||
function _describeFailure(src) {
|
||||
if (typeof fetch !== 'function') return Promise.resolve('');
|
||||
return fetch(src, { credentials: 'same-origin', cache: 'no-store' })
|
||||
.then(function (r) { return r.ok ? '' : ' (HTTP ' + r.status + ')'; })
|
||||
.catch(function () { return ' (réseau injoignable)'; });
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge une lib vendorisée, avec une seconde tentative qui contourne le
|
||||
* cache HTTP : les libs sont servies en `max-age=86400`, donc une entrée
|
||||
* tronquée par une coupure réseau condamnait le lecteur jusqu'au vidage
|
||||
* manuel du cache navigateur. Seuls les succès sont mémorisés — une
|
||||
* promesse rejetée gardée en cache rendait tout réessai impossible pour
|
||||
* le reste de la session.
|
||||
*/
|
||||
function loadScript(src) {
|
||||
if (_scriptCache[src]) return _scriptCache[src];
|
||||
|
||||
var attempt = _injectScript(src)
|
||||
.catch(function () {
|
||||
return _delay(400).then(function () {
|
||||
return _injectScript(
|
||||
src + (src.indexOf('?') === -1 ? '?' : '&') + 'reload=' + Date.now()
|
||||
);
|
||||
});
|
||||
})
|
||||
.catch(function () {
|
||||
return _describeFailure(src).then(function (why) {
|
||||
throw new Error('Échec du chargement : ' + src + why);
|
||||
});
|
||||
});
|
||||
|
||||
_scriptCache[src] = attempt;
|
||||
attempt.catch(function () { delete _scriptCache[src]; });
|
||||
return attempt;
|
||||
}
|
||||
|
||||
/** Ouvre la connexion vers l'hôte du flux avant même de connaître l'URL finale. */
|
||||
@@ -253,6 +303,11 @@
|
||||
}
|
||||
});
|
||||
}).catch(function (err) {
|
||||
// hls.js indisponible : plutôt que d'échouer, tenter les chemins qui
|
||||
// ne demandent aucune lib (HLS natif Safari/iOS, sinon lecture directe
|
||||
// si le navigateur sait décoder le conteneur).
|
||||
self.log(err.message);
|
||||
if (self._canPlayNativeHls()) { self._playDirect(self.url); return; }
|
||||
self.onError(err.message);
|
||||
});
|
||||
};
|
||||
@@ -267,6 +322,24 @@
|
||||
}
|
||||
self._createMpegts(isLive);
|
||||
}).catch(function (err) {
|
||||
// mpegts.js indisponible (build incomplet, coupure réseau, quota du
|
||||
// rate limiter…) : le même flux reste lisible par la route HLS, où
|
||||
// FFmpeg réencode déjà l'audio en AAC. Une seconde de latence en plus
|
||||
// vaut mieux qu'un écran d'erreur sur une chaîne parfaitement lisible.
|
||||
var hlsUrl = self._hlsEquivalent(self.url);
|
||||
self.log(err.message + (hlsUrl ? ' — bascule sur le chemin HLS' : ''));
|
||||
if (hlsUrl) {
|
||||
self.url = hlsUrl;
|
||||
self.onLoading('Ouverture du flux');
|
||||
if (self._canPlayNativeHls()) { self._playDirect(hlsUrl); return; }
|
||||
return self._startHls();
|
||||
}
|
||||
// Aucun équivalent HLS (flux direct fourni par la playlist) : dernier
|
||||
// recours, laisser le navigateur décoder lui-même le conteneur.
|
||||
if (self.video.canPlayType('video/mp2t') !== '') {
|
||||
self._playDirect(self.url);
|
||||
return;
|
||||
}
|
||||
self.onError(err.message);
|
||||
});
|
||||
};
|
||||
@@ -284,7 +357,13 @@
|
||||
// 64 Ko en profil « fast » contre 512 Ko auparavant.
|
||||
stashInitialSize: this.profile.mpegtsStash,
|
||||
maxStashSize: 30 * 1024 * 1024,
|
||||
liveBufferLatencyChasing: false,
|
||||
// Rattrapage du direct : sans lui, chaque micro-coupure fait dériver
|
||||
// la lecture derrière le direct (latence qui s'accumule). Activé
|
||||
// uniquement en profil « fast » — les profils élargis privilégient
|
||||
// la stabilité du buffer.
|
||||
liveBufferLatencyChasing: isLive && this.profile.name === 'fast',
|
||||
liveBufferLatencyMaxLatency: 5,
|
||||
liveBufferLatencyMinRemain: 1,
|
||||
lazyLoad: false
|
||||
}
|
||||
);
|
||||
@@ -341,13 +420,15 @@
|
||||
this._attemptPlay();
|
||||
};
|
||||
|
||||
/// `/api/live/<id>.ts` → `/api/live/<id>/source/playlist.m3u8`.
|
||||
/// `/api/live/<id>/turbo.ts` (ou l'ancien `/api/live/<id>.ts`)
|
||||
/// → `/api/live/<id>/source/playlist.m3u8`.
|
||||
///
|
||||
/// Le préréglage `source` garde la vidéo en copie de flux (`-c:v copy`) :
|
||||
/// seul l'audio est réencodé, le coût processeur reste négligeable.
|
||||
/// Filet de sécurité : la route turbo réencode déjà l'audio en AAC côté
|
||||
/// serveur, donc ce fallback ne devrait plus jamais se déclencher — il
|
||||
/// reste pour couvrir un flux sans piste audio exploitable du tout.
|
||||
/// Renvoie `null` si l'URL n'est pas un flux live direct — rien à tenter.
|
||||
XFPlayer.prototype._hlsEquivalent = function (url) {
|
||||
var match = /^(.*\/api\/live\/)([^/?#]+)\.ts(\?.*)?$/.exec(url);
|
||||
var match = /^(.*\/api\/live\/)([^/?#]+)(?:\/turbo)?\.ts(\?.*)?$/.exec(url);
|
||||
if (!match) return null;
|
||||
return match[1] + match[2] + '/source/playlist.m3u8';
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user