tagradio + mixcloud (fun with subtitles)
commit
7053a5bbd4
@ -0,0 +1 @@
|
|||||||
|
*.mp3
|
@ -0,0 +1,6 @@
|
|||||||
|
# vosk can also output JSON that includes the timing of each individual
|
||||||
|
# detected WORD!
|
||||||
|
# NOTE: I had an error when I did this and needed to PATCH some PYTHON code in VOSK
|
||||||
|
# see VOSKPATCH.TXT
|
||||||
|
vosk-transcriber -l en-us -i worm25_mia_60.wav -t json -o worm25_mia_60.json
|
||||||
|
|
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
ap = argparse.ArgumentParser("convert srt into vtt")
|
||||||
|
ap.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)
|
||||||
|
ap.add_argument('outfile', nargs='?', type=argparse.FileType('w'), default=sys.stdout)
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
print ("WEBVTT\n", file=args.outfile)
|
||||||
|
for line in args.infile:
|
||||||
|
print (re.sub(r"(\d\d:\d\d:\d\d),(\d\d\d) --> (\d\d:\d\d:\d\d),(\d\d\d)", r"\1.\2 --> \3.\4", line.rstrip()), file=args.outfile)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<video src="w25mia60.mp3" controls style="width: 100%; height: 320px;">
|
||||||
|
<track default kind="captions" label="vosk" src="w25mia60.vtt"></track>
|
||||||
|
</video>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<audio src="w25mia60.mp3" controls style="width: 100%">
|
||||||
|
<track default id="captions" kind="metadata" label="vosk" src="w25mia60.vtt"></track>
|
||||||
|
</audio>
|
||||||
|
|
||||||
|
<div id="caption" style="text-align: center; padding: 25px; font-size: 42px; color: line">caption here</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let captrack = document.querySelector("track#captions");
|
||||||
|
let capdiv = document.querySelector("#caption");
|
||||||
|
captrack.addEventListener("cuechange", (e) => {
|
||||||
|
console.log('track: cuechange', e);
|
||||||
|
let text = captrack.track.activeCues[0]?.text || "";
|
||||||
|
console.log(text);
|
||||||
|
capdiv.innerHTML = text;
|
||||||
|
});
|
||||||
|
captrack.track.mode = "hidden";
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,110 @@
|
|||||||
|
WEBVTT
|
||||||
|
|
||||||
|
1
|
||||||
|
00:00:00.075 --> 00:00:02.610
|
||||||
|
have a particular connection to worms inner
|
||||||
|
|
||||||
|
2
|
||||||
|
00:00:02.610 --> 00:00:05.970
|
||||||
|
and outer workings i wanted to make
|
||||||
|
|
||||||
|
3
|
||||||
|
00:00:05.970 --> 00:00:08.640
|
||||||
|
the series because one has become over
|
||||||
|
|
||||||
|
4
|
||||||
|
00:00:08.640 --> 00:00:10.710
|
||||||
|
twenty five years and institution
|
||||||
|
|
||||||
|
5
|
||||||
|
00:00:11.460 --> 00:00:14.130
|
||||||
|
but an institution built with and for
|
||||||
|
|
||||||
|
6
|
||||||
|
00:00:14.130 --> 00:00:16.110
|
||||||
|
and from a d i y spirits
|
||||||
|
|
||||||
|
7
|
||||||
|
00:00:16.590 --> 00:00:19.080
|
||||||
|
and something that it still retains it's
|
||||||
|
|
||||||
|
8
|
||||||
|
00:00:19.080 --> 00:00:20.490
|
||||||
|
the nature of do i was spaces
|
||||||
|
|
||||||
|
9
|
||||||
|
00:00:20.490 --> 00:00:22.710
|
||||||
|
of course and any cultural spaces that
|
||||||
|
|
||||||
|
10
|
||||||
|
00:00:22.710 --> 00:00:24.390
|
||||||
|
people who make it come and go
|
||||||
|
|
||||||
|
11
|
||||||
|
00:00:24.570 --> 00:00:25.830
|
||||||
|
the name on the building stays the
|
||||||
|
|
||||||
|
12
|
||||||
|
00:00:25.830 --> 00:00:28.260
|
||||||
|
same but the vibe changes and the
|
||||||
|
|
||||||
|
13
|
||||||
|
00:00:28.260 --> 00:00:29.880
|
||||||
|
sense of identity shifts
|
||||||
|
|
||||||
|
14
|
||||||
|
00:00:31.020 --> 00:00:33.000
|
||||||
|
worm is a place of invention and
|
||||||
|
|
||||||
|
15
|
||||||
|
00:00:33.000 --> 00:00:35.880
|
||||||
|
reinvention and with the constant motion certain
|
||||||
|
|
||||||
|
16
|
||||||
|
00:00:35.880 --> 00:00:39.120
|
||||||
|
stories and memories do fade away sometimes
|
||||||
|
|
||||||
|
17
|
||||||
|
00:00:39.120 --> 00:00:39.870
|
||||||
|
quite quickly
|
||||||
|
|
||||||
|
18
|
||||||
|
00:00:40.770 --> 00:00:42.563
|
||||||
|
the idea of this history of why
|
||||||
|
|
||||||
|
19
|
||||||
|
00:00:42.563 --> 00:00:44.790
|
||||||
|
i'm not the only possible history of
|
||||||
|
|
||||||
|
20
|
||||||
|
00:00:44.790 --> 00:00:47.160
|
||||||
|
course is to try and capture a
|
||||||
|
|
||||||
|
21
|
||||||
|
00:00:47.160 --> 00:00:48.750
|
||||||
|
few of those stories with the people
|
||||||
|
|
||||||
|
22
|
||||||
|
00:00:48.750 --> 00:00:50.748
|
||||||
|
that i've met and people that maria
|
||||||
|
|
||||||
|
23
|
||||||
|
00:00:50.748 --> 00:00:52.680
|
||||||
|
it has known along the way
|
||||||
|
|
||||||
|
24
|
||||||
|
00:00:53.790 --> 00:00:54.780
|
||||||
|
but i'm not going to begin at
|
||||||
|
|
||||||
|
25
|
||||||
|
00:00:54.780 --> 00:00:56.880
|
||||||
|
the beginning that would be logical but
|
||||||
|
|
||||||
|
26
|
||||||
|
00:00:56.880 --> 00:00:59.370
|
||||||
|
actually have already begun obviously and today's
|
||||||
|
|
||||||
|
27
|
||||||
|
00:00:59.370 --> 00:00:59.970
|
||||||
|
episode
|
||||||
|
|
@ -0,0 +1,132 @@
|
|||||||
|
(function (global, factory) {
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define(['exports', 'module'], factory);
|
||||||
|
} else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
|
||||||
|
factory(exports, module);
|
||||||
|
} else {
|
||||||
|
var mod = {
|
||||||
|
exports: {}
|
||||||
|
};
|
||||||
|
factory(mod.exports, mod);
|
||||||
|
global.fetchJsonp = mod.exports;
|
||||||
|
}
|
||||||
|
})(this, function (exports, module) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var defaultOptions = {
|
||||||
|
timeout: 5000,
|
||||||
|
jsonpCallback: 'callback',
|
||||||
|
jsonpCallbackFunction: null
|
||||||
|
};
|
||||||
|
|
||||||
|
function generateCallbackFunction() {
|
||||||
|
return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearFunction(functionName) {
|
||||||
|
// IE8 throws an exception when you try to delete a property on window
|
||||||
|
// http://stackoverflow.com/a/1824228/751089
|
||||||
|
try {
|
||||||
|
delete window[functionName];
|
||||||
|
} catch (e) {
|
||||||
|
window[functionName] = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeScript(scriptId) {
|
||||||
|
var script = document.getElementById(scriptId);
|
||||||
|
if (script) {
|
||||||
|
document.getElementsByTagName('head')[0].removeChild(script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchJsonp(_url) {
|
||||||
|
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
|
||||||
|
|
||||||
|
// to avoid param reassign
|
||||||
|
var url = _url;
|
||||||
|
var timeout = options.timeout || defaultOptions.timeout;
|
||||||
|
var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
|
||||||
|
|
||||||
|
var timeoutId = undefined;
|
||||||
|
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
|
||||||
|
var scriptId = jsonpCallback + '_' + callbackFunction;
|
||||||
|
|
||||||
|
window[callbackFunction] = function (response) {
|
||||||
|
resolve({
|
||||||
|
ok: true,
|
||||||
|
// keep consistent with fetch API
|
||||||
|
json: function json() {
|
||||||
|
return Promise.resolve(response);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (timeoutId) clearTimeout(timeoutId);
|
||||||
|
|
||||||
|
removeScript(scriptId);
|
||||||
|
|
||||||
|
clearFunction(callbackFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if the user set their own params, and if not add a ? to start a list of params
|
||||||
|
url += url.indexOf('?') === -1 ? '?' : '&';
|
||||||
|
|
||||||
|
var jsonpScript = document.createElement('script');
|
||||||
|
jsonpScript.setAttribute('src', '' + url + jsonpCallback + '=' + callbackFunction);
|
||||||
|
if (options.charset) {
|
||||||
|
jsonpScript.setAttribute('charset', options.charset);
|
||||||
|
}
|
||||||
|
if (options.nonce) {
|
||||||
|
jsonpScript.setAttribute('nonce', options.nonce);
|
||||||
|
}
|
||||||
|
if (options.referrerPolicy) {
|
||||||
|
jsonpScript.setAttribute('referrerPolicy', options.referrerPolicy);
|
||||||
|
}
|
||||||
|
if (options.crossorigin) {
|
||||||
|
jsonpScript.setAttribute('crossorigin', 'true');
|
||||||
|
}
|
||||||
|
jsonpScript.id = scriptId;
|
||||||
|
document.getElementsByTagName('head')[0].appendChild(jsonpScript);
|
||||||
|
|
||||||
|
timeoutId = setTimeout(function () {
|
||||||
|
reject(new Error('JSONP request to ' + _url + ' timed out'));
|
||||||
|
|
||||||
|
clearFunction(callbackFunction);
|
||||||
|
removeScript(scriptId);
|
||||||
|
window[callbackFunction] = function () {
|
||||||
|
clearFunction(callbackFunction);
|
||||||
|
};
|
||||||
|
}, timeout);
|
||||||
|
|
||||||
|
// Caught if got 404/500
|
||||||
|
jsonpScript.onerror = function () {
|
||||||
|
reject(new Error('JSONP request to ' + _url + ' failed'));
|
||||||
|
|
||||||
|
clearFunction(callbackFunction);
|
||||||
|
removeScript(scriptId);
|
||||||
|
if (timeoutId) clearTimeout(timeoutId);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// export as global function
|
||||||
|
/*
|
||||||
|
let local;
|
||||||
|
if (typeof global !== 'undefined') {
|
||||||
|
local = global;
|
||||||
|
} else if (typeof self !== 'undefined') {
|
||||||
|
local = self;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
local = Function('return this')();
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('polyfill failed because global object is unavailable in this environment');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
local.fetchJsonp = fetchJsonp;
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = fetchJsonp;
|
||||||
|
});
|
@ -0,0 +1,41 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>minimal archive.org search</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>This is a minimal form to send a search request to archive.org</p>
|
||||||
|
<form action="https://archive.org/advancedsearch.php">
|
||||||
|
<input size="50" type="text" name="q" value="subject:"field recording"">
|
||||||
|
<input type="submit" value="Search">
|
||||||
|
<!-- the rest are hidden -->
|
||||||
|
<input type="hidden" name="fl[]" value="date">
|
||||||
|
<input type="hidden" name="fl[]" value="description">
|
||||||
|
<input type="hidden" name="fl[]" value="format">
|
||||||
|
<input type="hidden" name="fl[]" value="identifier">
|
||||||
|
<input type="hidden" name="fl[]" value="licenseurl">
|
||||||
|
<input type="hidden" name="fl[]" value="mediatype">
|
||||||
|
<input type="hidden" name="fl[]" value="name">
|
||||||
|
<input type="hidden" name="fl[]" value="rights">
|
||||||
|
<input type="hidden" name="fl[]" value="subject">
|
||||||
|
<input type="hidden" name="fl[]" value="title">
|
||||||
|
<input type="hidden" name="fl[]" value="type">
|
||||||
|
<input type="hidden" name="sort[]" value="year desc">
|
||||||
|
<input type="hidden" name="sort[]" value="identifier asc">
|
||||||
|
<input id="numresults" type="hidden" name="rows" value="10">
|
||||||
|
<input type="hidden" name="page" value="1">
|
||||||
|
<input type="hidden" name="output" value="json">
|
||||||
|
<!-- <input type="hidden" name="output" value="tables">
|
||||||
|
<input type="hidden" name="callback" value="callback"> -->
|
||||||
|
</form>
|
||||||
|
<div id="results"></div>
|
||||||
|
<script src="fetch-jsonp.js"></script>
|
||||||
|
<script src="tagradio.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,56 @@
|
|||||||
|
// https://github.com/camsong/fetch-jsonp
|
||||||
|
// https://raw.githubusercontent.com/camsong/fetch-jsonp/refs/heads/master/src/fetch-jsonp.js
|
||||||
|
|
||||||
|
let form = document.querySelector("form");
|
||||||
|
|
||||||
|
form.addEventListener("submit", event => {
|
||||||
|
// console.log("GO NO FURTHER FORM... I'll take it from here");
|
||||||
|
event.preventDefault();
|
||||||
|
let formdata = new FormData(form);
|
||||||
|
let usp = new URLSearchParams(formdata);
|
||||||
|
console.log("urlsearchparams", usp.toString());
|
||||||
|
let results_div = document.querySelector("#results");
|
||||||
|
fetchJsonp("https://archive.org/advancedsearch.php?"+usp.toString())
|
||||||
|
.then(resp => resp.json())
|
||||||
|
.then(data => {
|
||||||
|
console.log("data", data);
|
||||||
|
data.response.docs.forEach (doc => {
|
||||||
|
console.log(doc);
|
||||||
|
let div = document.createElement("div");
|
||||||
|
let a = document.createElement("a");
|
||||||
|
let item_url = `https://archive.org/details/${doc.identifier}`;
|
||||||
|
let item_metadata_url = `https://archive.org/metadata/${doc.identifier}`;
|
||||||
|
a.href = item_url;
|
||||||
|
a.textContent = doc.title;
|
||||||
|
div.appendChild(a);
|
||||||
|
results_div.appendChild(div);
|
||||||
|
|
||||||
|
fetchJsonp(item_metadata_url)
|
||||||
|
.then (resp => resp.json())
|
||||||
|
.then(item_data => {
|
||||||
|
console.log("*", item_data);
|
||||||
|
let file_url = `https://${item_data.server}${item_data.dir}/`;
|
||||||
|
let mp3_files = item_data.files.filter(f => f.format == "VBR MP3");
|
||||||
|
let first_file_url = file_url + encodeURI(mp3_files[0].name);
|
||||||
|
let audio = document.createElement("audio");
|
||||||
|
div.appendChild(audio);
|
||||||
|
audio.controls = true;
|
||||||
|
audio.src = first_file_url;
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
// here we have access to the response data...
|
||||||
|
})
|
||||||
|
|
||||||
|
// fetch("https://archive.org/advancedsearch.php", {
|
||||||
|
// method: "cors",
|
||||||
|
// body: formdata
|
||||||
|
// }).then(resp => resp.json())
|
||||||
|
// .then(data => {
|
||||||
|
// console.log("data", data);
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
})
|
Loading…
Reference in New Issue