Skip to content
This repository has been archived by the owner on Nov 5, 2023. It is now read-only.

Commit

Permalink
SRT initial work
Browse files Browse the repository at this point in the history
  • Loading branch information
curtgrimes committed Oct 27, 2019
1 parent fe91d28 commit ac6259e
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 2 deletions.
2 changes: 2 additions & 0 deletions app/assets/scss/app.scss
Expand Up @@ -141,6 +141,8 @@ $modal-content-box-shadow-xs: $modal-content-box-shadow-sm-up;
@import '~bootstrap/scss/_utilities.scss';
@import '~bootstrap/scss/_print.scss';

@import 'bootstrap-vue/src/index.scss';

.logo-text {
font-family: $headings-font-family;
text-transform: uppercase;
Expand Down
44 changes: 42 additions & 2 deletions app/pages/captioner/settings/general/index.vue
Expand Up @@ -46,6 +46,34 @@
</transition>
<div class="clearfix"></div>
<hr />

<div class="row">
<div class="col-md-4">
<label
for="adjust-speed-accuracy"
class="mb-0 form-group form-inline float-left"
>Speed vs. accuracy</label>
</div>
<div class="col-md-8">
<div class="d-flex">
<div class="small text-muted font-weight-bold text-right">More real-time captions</div>
<div class="form-group mx-auto w-100 px-2">
<b-form-input
id="adjust-speed-accuracy"
v-model="value"
type="range"
min="2000"
max="5000"
step="1000"
></b-form-input>
</div>
<div class="small text-muted font-weight-bold text-left">More real-time captions</div>
</div>
</div>
</div>
<div class="clearfix"></div>
<hr />

<label for="show-volume-meter" class="mb-0">Show volume meter when volume level is low</label>
<b-form-checkbox id="show-volume-meter" v-model="volumeMeterShow" switch class="float-right"></b-form-checkbox>
<div class="clearfix"></div>
Expand Down Expand Up @@ -223,11 +251,23 @@
</template>

<script>
import { BFormCheckbox } from 'bootstrap-vue';
import bBtn from 'bootstrap-vue/es/components/button/button';
import bFormInput from 'bootstrap-vue/es/components/form-input/form-input';
import bFormCheckbox from 'bootstrap-vue/es/components/form-checkbox/form-checkbox';
import bListGroup from 'bootstrap-vue/es/components/list-group/list-group';
import bListGroupItem from 'bootstrap-vue/es/components/list-group/list-group-item';
import bNavbar from 'bootstrap-vue/es/components/navbar/navbar';
import bDropdown from 'bootstrap-vue/es/components/dropdown/dropdown';
export default {
components: {
BFormCheckbox,
bBtn,
bFormInput,
bFormCheckbox,
bListGroup,
bListGroupItem,
bNavbar,
bDropdown,
},
middleware: ['settings-meta'],
meta: {
Expand Down
197 changes: 197 additions & 0 deletions app/pages/srt.vue
@@ -0,0 +1,197 @@
<template>
<div class="bg-white">
<h3>SRT test</h3>
<pre>
{{stabilizedTranscript}}
</pre>
</div>
</template>

<script>
export default {
mounted: function() {
const MAX_LINE_LENGTH_CHARACTERS = 42;
let line1 = [],
line2 = [],
line1CharacterCount = 0,
line2CharacterCount = 0,
linePairs = [];
for (let i = 0; i < this.stabilizedTranscript.length; i++) {
// Decide whether to start a new pair of lines
if (
// There hasn't been too much time since the last word
// There is a previous item
!this.stabilizedTranscript[i - 1] ||
// It happened less than 2000 MS before the current item
this.stabilizedTranscript[i].time -
this.stabilizedTranscript[i - 1].time <=
2000
) {
// Figure out whether to put it on line 1, line 2, or on a new line 1
if (
// Adding this wouldn't make line 1 too long
line1CharacterCount + this.stabilizedTranscript[i].text.length <=
MAX_LINE_LENGTH_CHARACTERS &&
// And we haven't already started adding to line 2
line2CharacterCount === 0
) {
line1.push(this.stabilizedTranscript[i]);
line1CharacterCount += this.stabilizedTranscript[i].text.length;
} else if (
// Adding this wouldn't make line 2 too long
line2CharacterCount + this.stabilizedTranscript[i].text.length <=
MAX_LINE_LENGTH_CHARACTERS
) {
line2.push(this.stabilizedTranscript[i]);
line2CharacterCount += this.stabilizedTranscript[i].text.length;
} else {
// Start a new pair of lines
linePairs.push({ line1, line2 });
line1 = [];
line2 = [];
line1CharacterCount = 0;
line2CharacterCount = 0;
// Add to line 1
line1.push(this.stabilizedTranscript[i]);
line1CharacterCount += this.stabilizedTranscript[i].text.length;
}
} else {
// Start a new pair of lines
linePairs.push({ line1, line2 });
line1 = [];
line2 = [];
line1CharacterCount = 0;
line2CharacterCount = 0;
// Add to line 1
line1.push(this.stabilizedTranscript[i]);
line1CharacterCount += this.stabilizedTranscript[i].text.length;
}
}
if (line1.length || line2.length) {
// One final push
linePairs.push({ line1, line2 });
}
let srtStartTime;
for (let i = 0; i < linePairs.length; i++) {
function getLastWord(linePairs) {
if (linePairs.line2[linePairs.line2.length - 1]) {
// Line 2 has a last item
return linePairs.line2[linePairs.line2.length - 1];
} else {
// Return line 1's last item
return linePairs.line1[linePairs.line1.length - 1];
}
}
function getDurationString(ms) {
// Given a count of milliseconds, get the duration back in the format
// HH:MM:SS,mmm
const secondDuration = 1000;
const minuteDuration = secondDuration * 60;
const hourDuration = minuteDuration * 60;
// 7200000 = 2 hours
let hours = Math.floor(ms / hourDuration);
let minutes = Math.floor((ms % hourDuration) / minuteDuration);
let seconds = Math.floor(
((ms % hourDuration) % minuteDuration) / secondDuration
);
let milliseconds =
((ms % hourDuration) % minuteDuration) % secondDuration;
function zeroPadded(num, digits) {
return ('0'.repeat(digits) + num).substr(digits * -1, digits);
}
return (
zeroPadded(hours, 2) +
':' +
zeroPadded(minutes, 2) +
':' +
zeroPadded(seconds, 2) +
',' +
zeroPadded(milliseconds, 3)
);
}
let startTime = linePairs[i].line1[0].time;
let endTime = getLastWord(linePairs[i]).time;
if (!srtStartTime) {
srtStartTime = startTime;
}
let startTimestampString = getDurationString(startTime - srtStartTime);
let endTimestampString = getDurationString(endTime - srtStartTime);
console.log(i + 1);
console.log(startTimestampString + ' --> ' + endTimestampString);
console.log(linePairs[i].line1.map((t) => t.text).join(' '));
console.log(linePairs[i].line2.map((t) => t.text).join(' '));
console.log('');
}
},
data: function() {
return {
stabilizedTranscript: [
{ time: 1556680498907, text: 'fluent' },
{ time: 1556680498907, text: 'is' },
{ time: 1556680498907, text: 'a' },
{ time: 1556680499906, text: 'family' },
{ time: 1556680499906, text: 'of' },
{ time: 1556680500908, text: 'localization' },
{ time: 1556680502904, text: 'specifications' },
{ time: 1556680503796, text: 'implementations' },
{ time: 1556680505905, text: 'and' },
{ time: 1556680505905, text: 'good' },
{ time: 1556680505905, text: 'practices' },
{ time: 1556680505905, text: 'developed' },
{ time: 1556680505905, text: 'by' },
{ time: 1556680506908, text: 'Mozilla' },
{ time: 1556680508906, text: 'with' },
{ time: 1556680508906, text: 'fluent' },
{ time: 1556680509907, text: 'translators' },
{ time: 1556680510906, text: 'can' },
{ time: 1556680510906, text: 'create' },
{ time: 1556680512192, text: 'expressive' },
{ time: 1556680513905, text: 'translations' },
{ time: 1556680513905, text: 'that' },
{ time: 1556680513905, text: 'sound' },
{ time: 1556680513905, text: 'great' },
{ time: 1556680514904, text: 'in' },
{ time: 1556680514904, text: 'their' },
{ time: 1556680514904, text: 'language' },
{ time: 1556680517904, text: 'today' },
{ time: 1556680517904, text: "we're" },
{ time: 1556680517904, text: 'announcing' },
{ time: 1556680517904, text: 'version' },
{ time: 1556680518907, text: '1.0' },
{ time: 1556680518907, text: 'of' },
{ time: 1556680519906, text: 'the' },
{ time: 1556680519906, text: 'fluid' },
{ time: 1556680519906, text: 'file' },
{ time: 1556680520904, text: 'format' },
{ time: 1556680520904, text: 'specification' },
{ time: 1556680522391, text: 'were' },
{ time: 1556680522391, text: 'inviting' },
{ time: 1556680522692, text: 'translation' },
{ time: 1556680522992, text: 'to' },
{ time: 1556680523291, text: 'authors' },
{ time: 1556680524492, text: 'to' },
{ time: 1556680524492, text: 'try' },
{ time: 1556680524492, text: 'it' },
{ time: 1556680524492, text: 'out' },
{ time: 1556680524492, text: 'and' },
{ time: 1556680524492, text: 'provide' },
{ time: 1556680525091, text: 'feedback' },
],
};
},
};
</script>
8 changes: 8 additions & 0 deletions app/store/captioner.js
Expand Up @@ -32,6 +32,7 @@ export const state = () => ({
delay: 0,
cursorable: [],
stabilized: '',
stabilizedWithTimings: [],
},
totalCaptioningSeconds: 0,
lastStart: null,
Expand Down Expand Up @@ -697,6 +698,8 @@ export const mutations = {
},
CLEAR_TRANSCRIPT_FINAL(state) {
state.transcript.final = '';
state.transcript.stabilized = '';
state.transcript.stabilizedWithTimings = [];
},
CLEAR_TRANSCRIPT_TYPED(state) {
state.transcript.typed = '';
Expand All @@ -717,6 +720,11 @@ export const mutations = {
transcript
}) {
state.transcript.stabilized += transcript + ' ';

state.transcript.stabilizedWithTimings.push({
time: Date.now() - 2500,
text: transcript,
});
},

VOLUME_TOO_LOW(state, {
Expand Down

0 comments on commit ac6259e

Please sign in to comment.