This commit is contained in:
Thomas Forgione 2021-06-21 14:34:27 +02:00
parent d1bd418e89
commit b41c62e938
5 changed files with 134 additions and 130 deletions

View File

@ -11,7 +11,7 @@
<script src="js/main.js"></script> <script src="js/main.js"></script>
<script src="js/ports.js"></script> <script src="js/ports.js"></script>
<script> <script>
embed({ PolymnyVideo.embed({
node: document.getElementById("container"), node: document.getElementById("container"),
url: "video/manifest.m3u8", url: "video/manifest.m3u8",
}); });

View File

@ -14,118 +14,129 @@ Object.defineProperty(HTMLElement.prototype, "polymnyVideoDocument", {
} }
}); });
function embed(options) { const PolymnyVideo = (function() {
if (!(options.node instanceof HTMLElement)) {
throw new Error("options.node must be an HTMLElement");
}
if (typeof options.url !== "string" && ! (options.url instanceof String)) { const PolymnyVideo = {};
throw new Error("options.url must be a string");
}
options.flags = options; PolymnyVideo.embed = function(options) {
options.width = window.innerWidth; if (!(options.node instanceof HTMLElement)) {
options.height = window.innerHeight; throw new Error("options.node must be an HTMLElement");
const app = Elm.Examples.Embed.init(options);
setupApp(app);
}
function setupApp(app) {
let hls;
app.ports.polymnyVideoInit.subscribe(function(arg) {
requestAnimationFrame(function() {
const video = document.getElementById(arg[0]);
if (Hls.isSupported()) {
hls = new Hls();
window.hls = hls;
hls.loadSource(arg[1]);
hls.on(Hls.Events.MANIFEST_PARSED, function(event, data) {
const availableQualities = hls.levels.map((l) => l.height);
availableQualities.unshift(0);
app.ports.polymnyVideoNowHasQualities.send(availableQualities);
});
hls.on(Hls.Events.LEVEL_SWITCHED, function(event, data) {
app.ports.polymnyVideoNowHasQuality.send({
auto: hls.autoLevelEnabled,
height: hls.levels[data.level].height
});
})
hls.on(Hls.Events.SUBTITLE_TRACKS_UPDATED, function(event, data) {
app.ports.polymnyVideoNowHasSubtitles.send(data.subtitleTracks);
});
hls.on(Hls.Events.SUBTITLE_TRACK_SWITCH, function(event, data) {
app.ports.polymnyVideoNowHasSubtitleTrack.send(data.id === -1 ? null : hls.subtitleTracks[data.id]);
});
hls.attachMedia(video);
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = arg[1];
}
});
});
app.ports.polymnyVideoPlayPause.subscribe(function(arg) {
const video = document.getElementById(arg);
if (video.paused) {
video.play();
} else {
video.pause();
} }
});
app.ports.polymnyVideoSeek.subscribe(function(arg) { if (typeof options.url !== "string" && ! (options.url instanceof String)) {
const video = document.getElementById(arg[0]); throw new Error("options.url must be a string");
video.currentTime = arg[1]; }
});
app.ports.polymnyVideoRequestFullscreen.subscribe(function(arg) { options.flags = options;
document.getElementById(arg + '-full').requestFullscreen(); options.width = window.innerWidth;
}); options.height = window.innerHeight;
app.ports.polymnyVideoExitFullscreen.subscribe(function(arg) { const app = Elm.Examples.Embed.init(options);
document.exitFullscreen(); PolymnyVideo.setup(app);
});
app.ports.polymnyVideoSetPlaybackRate.subscribe(function(arg) { };
const video = document.getElementById(arg[0]);
video.playbackRate = arg[1];
});
app.ports.polymnyVideoSetQuality.subscribe(function(arg) { PolymnyVideo.setup = function(app) {
var old = hls.currentLevel; let hls;
if (arg[1].auto) {
hls.currentLevel = -1; app.ports.polymnyVideoInit.subscribe(function(arg) {
} else { requestAnimationFrame(function() {
hls.levels.forEach((level, levelIndex) => { const video = document.getElementById(arg[0]);
if (level.height === arg[1].height) { if (Hls.isSupported()) {
hls.currentLevel = levelIndex; hls = new Hls();
window.hls = hls;
hls.loadSource(arg[1]);
hls.on(Hls.Events.MANIFEST_PARSED, function(event, data) {
const availableQualities = hls.levels.map((l) => l.height);
availableQualities.unshift(0);
app.ports.polymnyVideoNowHasQualities.send(availableQualities);
});
hls.on(Hls.Events.LEVEL_SWITCHED, function(event, data) {
app.ports.polymnyVideoNowHasQuality.send({
auto: hls.autoLevelEnabled,
height: hls.levels[data.level].height
});
})
hls.on(Hls.Events.SUBTITLE_TRACKS_UPDATED, function(event, data) {
app.ports.polymnyVideoNowHasSubtitles.send(data.subtitleTracks);
});
hls.on(Hls.Events.SUBTITLE_TRACK_SWITCH, function(event, data) {
app.ports.polymnyVideoNowHasSubtitleTrack.send(data.id === -1 ? null : hls.subtitleTracks[data.id]);
});
hls.attachMedia(video);
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = arg[1];
}
if (arg[2]) {
video.play();
} }
}); });
} });
if (old === hls.currentLevel) {
app.ports.polymnyVideoNowHasQuality.send({
auto: hls.autoLevelEnabled,
height: hls.currentLevel === -1 ? 0 : hls.levels[hls.currentLevel].height
});
}
});
app.ports.polymnyVideoSetVolume.subscribe(function(arg) { app.ports.polymnyVideoPlayPause.subscribe(function(arg) {
const video = document.getElementById(arg[0]); const video = document.getElementById(arg);
video.volume = arg[1].volume; if (video.paused) {
video.muted = arg[1].muted; video.play();
}); } else {
video.pause();
}
});
app.ports.polymnyVideoSetSubtitleTrack.subscribe(function(arg) { app.ports.polymnyVideoSeek.subscribe(function(arg) {
hls.subtitleDisplay = arg[1] !== -1; const video = document.getElementById(arg[0]);
hls.subtitleTrack = arg[1]; video.currentTime = arg[1];
}); });
} app.ports.polymnyVideoRequestFullscreen.subscribe(function(arg) {
document.getElementById(arg + '-full').requestFullscreen();
});
app.ports.polymnyVideoExitFullscreen.subscribe(function(arg) {
document.exitFullscreen();
});
app.ports.polymnyVideoSetPlaybackRate.subscribe(function(arg) {
const video = document.getElementById(arg[0]);
video.playbackRate = arg[1];
});
app.ports.polymnyVideoSetQuality.subscribe(function(arg) {
var old = hls.currentLevel;
if (arg[1].auto) {
hls.currentLevel = -1;
} else {
hls.levels.forEach((level, levelIndex) => {
if (level.height === arg[1].height) {
hls.currentLevel = levelIndex;
}
});
}
if (old === hls.currentLevel) {
app.ports.polymnyVideoNowHasQuality.send({
auto: hls.autoLevelEnabled,
height: hls.currentLevel === -1 ? 0 : hls.levels[hls.currentLevel].height
});
}
});
app.ports.polymnyVideoSetVolume.subscribe(function(arg) {
const video = document.getElementById(arg[0]);
video.volume = arg[1].volume;
video.muted = arg[1].muted;
});
app.ports.polymnyVideoSetSubtitleTrack.subscribe(function(arg) {
hls.subtitleDisplay = arg[1] !== -1;
hls.subtitleTrack = arg[1];
});
};
return PolymnyVideo;
})();

View File

@ -64,7 +64,7 @@ init flags =
|> Result.withDefault 0 |> Result.withDefault 0
( video, cmd ) = ( video, cmd ) =
Video.fromUrl url "video" Video.fromConfig { url = url, id = "video", autoplay = True }
in in
( { video = video, screenSize = ( width, height ) } ( { video = video, screenSize = ( width, height ) }
, Cmd.map VideoMsg cmd , Cmd.map VideoMsg cmd

View File

@ -3,7 +3,7 @@ port module Video exposing
, Settings(..) , Settings(..)
, SubtitleTrack , SubtitleTrack
, Video , Video
, fromUrl , fromConfig
, init , init
, nowHasQualities , nowHasQualities
, nowHasQuality , nowHasQuality
@ -44,10 +44,17 @@ type alias Video =
} }
fromUrl : String -> String -> ( Video, Cmd Msg ) type alias Config =
fromUrl url id = { url : String
( { url = url , id : String
, id = id , autoplay : Bool
}
fromConfig : Config -> ( Video, Cmd Msg )
fromConfig config =
( { url = config.url
, id = config.id
, playing = False , playing = False
, position = 0 , position = 0
, duration = 0 , duration = 0
@ -69,7 +76,7 @@ fromUrl url id =
, showIcon = Nothing , showIcon = Nothing
, showIconRequested = Nothing , showIconRequested = Nothing
} }
, init id url , init config.id config.url config.autoplay
) )
@ -265,12 +272,12 @@ update msg model =
( { model | showMiniature = miniature }, Cmd.none ) ( { model | showMiniature = miniature }, Cmd.none )
port polymnyVideoInit : ( String, String ) -> Cmd msg port polymnyVideoInit : ( String, String, Bool ) -> Cmd msg
init : String -> String -> Cmd msg init : String -> String -> Bool -> Cmd msg
init id url = init id url autoplay =
polymnyVideoInit ( id, url ) polymnyVideoInit ( id, url, autoplay )
port polymnyVideoPlayPause : String -> Cmd msg port polymnyVideoPlayPause : String -> Cmd msg

View File

@ -258,24 +258,10 @@ overlay model =
(Element.width Element.fill (Element.width Element.fill
:: Element.height Element.fill :: Element.height Element.fill
:: Font.color (Element.rgb 1 1 1) :: Font.color (Element.rgb 1 1 1)
:: (if not model.playing then
Background.color (Element.rgba 0 0 0 0.5)
else
Background.color (Element.rgba 0 0 0 0)
)
:: Events.overlay :: Events.overlay
) )
(case ( model.playing, model.showIcon ) of (case model.showIcon of
( False, _ ) -> Just icon ->
Element.el
[ Element.centerX
, Element.centerY
, Element.scale 10
]
(Icons.play True)
( _, Just icon ) ->
animatedEl fadeOutZoom animatedEl fadeOutZoom
[ Background.color (Element.rgb 0 0 0) [ Background.color (Element.rgb 0 0 0)
, Border.rounded 100 , Border.rounded 100