mirror of https://bitbucket.org/ausocean/av.git
audio-player: swap out the seperate input fields for a url field
This commit is contained in:
parent
a24bb4e0bb
commit
085f0e7437
|
@ -10,7 +10,7 @@
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body style="height: 100%">
|
<body style="height: 100%" onload="load();">
|
||||||
<div class="card m-auto" style="width: 40rem;">
|
<div class="card m-auto" style="width: 40rem;">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
@ -19,51 +19,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<form enctype="multipart/form-data" onsubmit="presubmit();">
|
URL: <input type="text" id="url" class="url mb-3 mx-3" onchange="load();"><button onclick="load();">Load</button>
|
||||||
<div class="form-group">
|
|
||||||
<label>App key:</label>
|
|
||||||
<input class="form-control form-control-sm" type="input" id="ak" name="ak">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Media ID:</label>
|
|
||||||
<input class="form-control form-control-sm" type="input" id="id" name="id">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Start date or timestamp:</label>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control form-control-sm" type="datetime-local" id="sd" name="sd" onchange="sync('sd', 'st', true);">
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control form-control-sm" type="input" id="st" name="st" onchange="sync('sd', 'sd', false);">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Finish date or timestamp:</label>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control form-control-sm" type="datetime-local" id="fd" name="fd" onchange="sync('fd', 'ft', true);">
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control form-control-sm" type="input" id="ft" name="ft" onchange="sync('fd', 'fd', false);">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<input class="btn btn-primary" type="submit" value="Get Audio" id="submit">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="hidden" id="ts">
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<span class="form-inline mb-3">
|
|
||||||
<label>MAC:</label>
|
|
||||||
<input type="input" class="form-control form-control-sm mx-sm-3" id="ma" placeholder="00:00:00:00:00:00">
|
|
||||||
<label>Pin:</label>
|
|
||||||
<input type="input" class="form-control form-control-sm mx-sm-3" id="pn" value="V0" style="width: 3rem">
|
|
||||||
<button class="btn-sm btn-secondary" onClick="updateMID('ma','pn','id');">Convert to Media ID</button>
|
|
||||||
</span>
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<audio class="mx-auto" controls="controls" id="audio">
|
<audio class="mx-auto" controls="controls" id="audio">
|
||||||
Your browser does not support the <code>audio</code> element.
|
Your browser does not support the <code>audio</code> element.
|
||||||
|
|
|
@ -58,88 +58,86 @@ function processData() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sync(dateID, tsID, dateChanged) {
|
// getQuery gets everything after the question mark in the URL.
|
||||||
if (dateChanged) { // Go from date to Unix timestamp.
|
function getQuery() {
|
||||||
var s = document.getElementById(dateID).value;
|
var regex = new RegExp("\\?(.*)");
|
||||||
if (s == "") {
|
var match = regex.exec(window.location.href);
|
||||||
document.getElementById(tsID).value = "";
|
if (match == null) {
|
||||||
|
return '';
|
||||||
} else {
|
} else {
|
||||||
if (s.length == 16) {
|
return decodeURIComponent(match[1].replace(/\+/g, " "));
|
||||||
s += ':00'; // Append seconds.
|
|
||||||
}
|
|
||||||
s += 'Z';
|
|
||||||
var dt = new Date(s)
|
|
||||||
document.getElementById(tsID).value = (dt.getTime() / 1000).toString();
|
|
||||||
}
|
|
||||||
} else { // Go from Unix timestamp to local date.
|
|
||||||
var s = document.getElementById(dateID).value;
|
|
||||||
if (s == "") {
|
|
||||||
document.getElementById(tsID).value = "";
|
|
||||||
} else {
|
|
||||||
var ts = parseInt(document.getElementById(tsID).value) * 1000;
|
|
||||||
var dt = new Date(ts).toISOString().slice(0, -1);
|
|
||||||
document.getElementById(dateID).value = dt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function presubmit() {
|
function load() {
|
||||||
if (document.getElementById('st').value == "" && document.getElementById('sd').value != "") {
|
var url = document.getElementById('url').value;
|
||||||
sync('sd', 'st', true);
|
if (url == "") {
|
||||||
|
url = getQuery()
|
||||||
|
document.getElementById('url').value = url;
|
||||||
}
|
}
|
||||||
if (document.getElementById('ft').value == "" && document.getElementById('fd').value != "") {
|
if (url[0] == '/') {
|
||||||
sync('fd', 'ft', true);
|
url = window.location.protocol + '//' + window.location.host + url;
|
||||||
}
|
}
|
||||||
if (document.getElementById('ft').value == "") {
|
if (url == "") {
|
||||||
document.getElementById('ts').value = document.getElementById('st').value;
|
|
||||||
} else {
|
|
||||||
document.getElementById('ts').value = document.getElementById('st').value + '-' + document
|
|
||||||
.getElementById('ft').value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// encodeMAC encodes a MAC address into a 48-bit integer.
|
|
||||||
function encodeMAC(mac) {
|
|
||||||
if (mac.length != 17) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
var enc = BigInt(0);
|
|
||||||
for (i = 15, shift = 0; i >= 0; i -= 3, shift += 8) {
|
|
||||||
var n = BigInt(parseInt(mac.substring(i, i + 2), 16));
|
|
||||||
enc += (n << BigInt(shift));
|
|
||||||
}
|
|
||||||
return enc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// encodePin encodes a pin into a 4-bit integer.
|
|
||||||
function encodePin(pin) {
|
|
||||||
var enc = Number(0);
|
|
||||||
if (pin.charAt(0) == 'S') {
|
|
||||||
enc = 8;
|
|
||||||
}
|
|
||||||
var pn = Number(pin.charAt(1) - '0');
|
|
||||||
if (pin.length > 2) {
|
|
||||||
pn = pn * 10 + Number(pin.CharAt(2) - '0');
|
|
||||||
}
|
|
||||||
enc |= pn;
|
|
||||||
return enc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// toMID returns a Media ID as a BigInt given a MAC address and a pin.
|
|
||||||
function toMID(mac, pin) {
|
|
||||||
if (mac == "" || pin == "") {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (encodeMAC(mac) << BigInt(4)) | BigInt(encodePin(pin))
|
|
||||||
}
|
|
||||||
|
|
||||||
// updateMID updates a Media ID element using values from MAC and pin elements.
|
|
||||||
function updateMID(mac, pin, mid) {
|
|
||||||
var macElem = document.getElementById(mac);
|
|
||||||
var pinElem = document.getElementById(pin);
|
|
||||||
var midElem = document.getElementById(mid);
|
|
||||||
if (!macElem || !pinElem || !midElem) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
midElem.value = toMID(macElem.value, pinElem.value).toString();
|
var video = document.getElementById('video');
|
||||||
|
|
||||||
|
if (Hls.isSupported()) {
|
||||||
|
console.log("play: browser can play HLS.")
|
||||||
|
var hls = new Hls({
|
||||||
|
autoStartLoad: true,
|
||||||
|
debug: true,
|
||||||
|
startFragPrefetch: true
|
||||||
|
});
|
||||||
|
hls.loadSource(url);
|
||||||
|
hls.attachMedia(video);
|
||||||
|
|
||||||
|
hls.on(Hls.Events.ERROR, function (event, data) {
|
||||||
|
if (data.fatal) {
|
||||||
|
switch (data.type) {
|
||||||
|
case Hls.ErrorTypes.NETWORK_ERROR:
|
||||||
|
console.log("play: fatal network error encountered, trying to recover.");
|
||||||
|
hls.startLoad();
|
||||||
|
break;
|
||||||
|
case Hls.ErrorTypes.MEDIA_ERROR:
|
||||||
|
console.log("play: fatal media error encountered, trying to recover.");
|
||||||
|
hls.recoverMediaError();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log("play: fatal error, cannot recover.");
|
||||||
|
hls.destroy();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("play: " + data.type + "error, " + data.details);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
hls.on(Hls.Events.MANIFEST_PARSED, function () {
|
||||||
|
playPromise = video.play();
|
||||||
|
if (playPromise !== undefined) {
|
||||||
|
playPromise.then(_ => {
|
||||||
|
console.log("play: autoplay started.")
|
||||||
|
document.getElementById('msg').innerHTML = "";
|
||||||
|
}).catch(error => {
|
||||||
|
console.log("play: autoplay was prevented.")
|
||||||
|
document.getElementById('msg').innerHTML = "Autoplay prevented. Hit play button to start."
|
||||||
|
// Remove the message once playing starts.
|
||||||
|
video.addEventListener('playing', function (e) {
|
||||||
|
document.getElementById('msg').innerHTML = "";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
||||||
|
console.log("play: browser can handle vnd.apple.mpegurl.")
|
||||||
|
video.src = url;
|
||||||
|
video.addEventListener('loadedmetadata', function () {
|
||||||
|
video.play();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("play: HLS not supported by browser.")
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue