From d58f6b1a4984526fbbbcdd9604d0f6b06fa8502b Mon Sep 17 00:00:00 2001 From: Alejandro Torrado Date: Thu, 23 May 2024 18:16:33 -0300 Subject: [PATCH] Hls Web support --- just_audio_web/lib/hlsjs.dart | 43 ++++++++++++++++++++++++++ just_audio_web/lib/hlsjs_loader.dart | 35 +++++++++++++++++++++ just_audio_web/lib/just_audio_web.dart | 11 +++++-- 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 just_audio_web/lib/hlsjs.dart create mode 100644 just_audio_web/lib/hlsjs_loader.dart diff --git a/just_audio_web/lib/hlsjs.dart b/just_audio_web/lib/hlsjs.dart new file mode 100644 index 000000000..ca603d57e --- /dev/null +++ b/just_audio_web/lib/hlsjs.dart @@ -0,0 +1,43 @@ +// @JS() +// library hls.js; + +import 'dart:js_interop'; +import 'package:web/web.dart' as web; + +@JS() +@staticInterop +class Hls { + external factory Hls(HlsConfig config); + external static bool isSupported(); +} + +extension HlsExtension on Hls { + external void stopLoad(); + external void loadSource(String videoSrc); + external void attachMedia(web.HTMLElement video); + external void on(String event, JSFunction callback); + external HlsConfig config; +} + +@JS() +@anonymous +@staticInterop +class HlsConfig { + external factory HlsConfig({JSFunction xhrSetup}); +} + +extension HlsConfigExtension on HlsConfig { + external JSFunction get xhrSetup; +} + +class ErrorData { + late final String type; + late final String details; + late final bool fatal; + + ErrorData(dynamic errorData) { + type = errorData.type as String; + details = errorData.details as String; + fatal = errorData.fatal as bool; + } +} diff --git a/just_audio_web/lib/hlsjs_loader.dart b/just_audio_web/lib/hlsjs_loader.dart new file mode 100644 index 000000000..bae91a4ec --- /dev/null +++ b/just_audio_web/lib/hlsjs_loader.dart @@ -0,0 +1,35 @@ +import 'dart:async'; +import 'dart:js_interop'; +import 'package:web/web.dart'; + +import 'hlsjs.dart'; + +const hlsjsCdnUrl = "https://cdn.jsdelivr.net/npm/hls.js@1"; + +Future? _loadHlsFuture; + +Future _loadHls() async { + var completer = Completer(); + var script = document.createElement('script'); + script.setAttribute('src', hlsjsCdnUrl); + script.setAttribute('async', ''); + script.addEventListener('load', (void _){completer.complete();}.toJS); + script.addEventListener('error', (void _){completer.completeError("Error loading Hls.js");}.toJS); + document.head!.append(script); + return completer.future; +} + +Future loadHls() async { + _loadHlsFuture ??= _loadHls(); + return _loadHlsFuture; +} + +void attachHlsjs(HTMLAudioElement element, String url){ + if (Hls.isSupported()) { + var hls = Hls(HlsConfig()); + hls.loadSource(url); + hls.attachMedia(element); + } else { + element.src = url; + } +} \ No newline at end of file diff --git a/just_audio_web/lib/just_audio_web.dart b/just_audio_web/lib/just_audio_web.dart index 32eef910e..0663e2c66 100644 --- a/just_audio_web/lib/just_audio_web.dart +++ b/just_audio_web/lib/just_audio_web.dart @@ -6,6 +6,7 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:just_audio_platform_interface/just_audio_platform_interface.dart'; +import 'package:just_audio_web/hlsjs_loader.dart'; import 'package:web/web.dart'; /// The web implementation of [JustAudioPlatform]. @@ -258,9 +259,15 @@ class Html5AudioPlayer extends JustAudioPlayer { final Uri uri, final Duration? initialPosition) async { transition(ProcessingStateMessage.loading); final src = uri.toString(); - if (src != _audioElement.src) { + var isHls = this._audioSourcePlayer is HlsAudioSourcePlayer;; + if (isHls || src != _audioElement.src) { _durationCompleter = Completer(); - _audioElement.src = src; + if (isHls){ + await loadHls(); + attachHlsjs(_audioElement, src); + } else { + _audioElement.src = src; + } _audioElement.playbackRate = _speed; _audioElement.preload = 'auto'; _audioElement.load();