New speaker/transcript submission

multichannel
HeNine 3 years ago
parent 596abf29cb
commit 7e1c9a36d8

@ -15,8 +15,9 @@ def cors(app):
HEADERS = [
("Access-Control-Allow-Credentials", "false"),
("Access-Control-Allow-Headers", "*"),
("Access-Control-Allow-Methods", "GET,HEAD"),
("Access-Control-Allow-Methods", "GET,HEAD,POST,PUT"),
("Access-Control-Allow-Origin", "*"),
("Access-Control-Expose-Headers", "*"),
("Access-Control-Max-Age", "86400"),
]

@ -38,6 +38,7 @@ def get_playlist(line_id):
end_time_iso = line.end_time.isoformat()
duration = line.end_time - line.start_time
return f"""#EXTM3U
#EXT-X-PLAYLIST-TYPE:vod
#EXT-X-TARGETDURATION:{duration.total_seconds()}
#EXT-X-PROGRAM-DATE-TIME:{start_time_iso}
#EXTINF:{duration.total_seconds()}
@ -78,7 +79,7 @@ def update_line(line_id):
def get_speakers():
db_conn = app.db_manager.get_conn()
speakers = database.query(db_conn, "SELECT name FROM buscribe_speakers;")
speakers = database.query(db_conn, "SELECT id, name FROM buscribe_speakers;")
return jsonify([{"id": speaker.id, "name": speaker.name} for speaker in speakers])

@ -6,11 +6,16 @@
<link href="video.js/dist/video-js.min.css" rel="stylesheet">
<link href="videojs-hls-quality-selector/dist/videojs-hls-quality-selector.css" rel="stylesheet">
<link href="jquery-ui-1.13.0.custom/jquery-ui.css" rel="stylesheet">
<link href="style.css" rel="stylesheet">
<script src="jquery-ui-1.13.0.custom/external/jquery/jquery.js"></script>
<script src="jquery-ui-1.13.0.custom/jquery-ui.js"></script>
<script src="script.js"></script>
<!-- <script src="videojs-contrib-quality-levels/dist/videojs-contrib-quality-levels.min.js"></script>-->
<!-- <script src="videojs-hls-quality-selector/dist/videojs-hls-quality-selector.min.js"></script>-->
@ -31,13 +36,16 @@
</div>
<div id="speakers">
<label for="speaker_input">Speakers</label><input id="speaker_input">
</div>
<div id="transcription">
<p id="original_transcription"></p>
<label for="new_transcription">New transcription</label><textarea id="new_transcription" rows="3" placeholder=""></textarea>
</div>
<button id="submit_button" onclick="submit()" type="button">Submit</button>
<script src="video.js/dist/video.min.js"></script>
</body>

@ -4,31 +4,121 @@ function pageReady() {
line_id = parseInt(params.get("line"), 10);
videojs("player", {
// src: "test.m3u8",
controls: true,
autoplay: false,
width: 900,
height: 420,
playbackRates: [0.5, 1, 1.25, 1.5, 2],
inactivityTimeout: 0,
controlBar: {
fullscreenToggle: true,
volumePanel: {
inline: false,
},
}
// src: "test.m3u8",
controls: true,
autoplay: false,
width: 900,
height: 420,
playbackRates: [0.5, 1, 1.25, 1.5, 2],
inactivityTimeout: 0,
controlBar: {
fullscreenToggle: true,
volumePanel: {
inline: false,
},
},
function () {
this.src({src: `//localhost:8005/professor/line/${line_id}/playlist.m3u8`});
});
sources: [{src: `//localhost:8005/professor/line/${line_id}/playlist.m3u8`}]
});
fetch(`//localhost:8005/professor/line/${line_id}`)
.then(response => response.json())
.then(fillLineInfo)
.then(fillLineInfo);
}
function fillLineInfo(line_json) {
document.getElementById("original_transcription").innerText = line_json.line_data.text
// document.getElementById("original_transcription").innerText = line_json.line_data.text;
document.getElementById("original_transcription").innerHTML = line_json.line_data.result
.map(word => `<span style="opacity: ${word.conf}">${word.word}</span>`).join(" ");
document.getElementById("new_transcription")
.attributes.getNamedItem("placeholder").value = line_json.line_data.text;
}
async function submit() {
const new_transcription = document.getElementById("new_transcription").value;
const new_speakers = await Promise.all(document.getElementById("speaker_input").value
.trim()
.split(",")
.filter(x => x !== "")
.map(speaker_raw => speaker_raw.trim())
.map(async function (speaker) {
for (const speaker_json of speakers) {
if (speaker_json.name === speaker) {
return speaker_json.id
}
}
return await fetch("//localhost:8005/professor/speaker",
{
method: "PUT",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(speaker)
}).then(response =>
parseInt(response.headers.get("Content-Location")
.split("/")
.pop(), 10));
}));
fetch(`//localhost:8005/professor/line/${line_id}`,
{
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({transcription: new_transcription, speakers: new_speakers})
})
}
$(function () {
fetch("//localhost:8005/professor/speaker")
.then(response => response.json())
.then(function (speakers_json) {
speakers = speakers_json;
speaker_names = speakers_json.map(x => x.name)
})
.then(function () {
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
$("#speaker_input")
// don't navigate away from the field on tab when selecting an item
.on("keydown", function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).autocomplete("instance").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function (request, response) {
// delegate back to autocomplete, but extract the last term
response($.ui.autocomplete.filter(
speaker_names, extractLast(request.term)));
},
focus: function () {
// prevent value inserted on focus
return false;
},
select: function (event, ui) {
var terms = split(this.value);
// remove the current input
terms.pop();
// add the selected item
terms.push(ui.item.value);
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(", ");
return false;
}
});
}
)
}
});

@ -1,6 +1,51 @@
@import "constants";
body {
color: aliceblue;
background: dimgray;
max-width: 900px;
}
#PlayerContainer {
}
label {
font-family: @sans-serif;
margin-top: 5px;
margin-bottom: 5px;
}
#speakers {
margin-top: 1em;
width: 100%;
display: flex;
flex-direction: column;
}
#transcription {
display: flex;
flex-direction: column;
width: 100%;
p {
font-family: @serif;
text-indent: 1.5em;
padding-top: 1ex;
padding-bottom: 1ex;
}
#new_transcription {
width: 894px;
height: 5em;
}
}
button {
margin-top: 5px;
margin-bottom: 5px;
}
Loading…
Cancel
Save