summaryrefslogtreecommitdiff
path: root/animism-align
diff options
context:
space:
mode:
Diffstat (limited to 'animism-align')
-rw-r--r--animism-align/README.md6
-rw-r--r--animism-align/cli/commands/peaks/parse.py13
-rw-r--r--animism-align/environment.yml21
-rw-r--r--animism-align/frontend/api/crud.reducer.js1
-rw-r--r--animism-align/frontend/views/align/align.css4
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotation.form.js7
-rw-r--r--animism-align/frontend/views/align/components/annotations/annotation.index.js2
-rw-r--r--animism-align/frontend/views/align/components/timeline/waveform.component.js9
-rw-r--r--animism-align/frontend/views/align/containers/timeline.container.js25
9 files changed, 63 insertions, 25 deletions
diff --git a/animism-align/README.md b/animism-align/README.md
index e08c35a..0e41ed4 100644
--- a/animism-align/README.md
+++ b/animism-align/README.md
@@ -2,7 +2,7 @@
Align a text to an audio file.
-## installation
+## Installation
First, install miniconda and node.
@@ -11,7 +11,7 @@ conda create env -f environment.yml
npm install
```
-## running the site
+## Running the site
Before running the commands, enter the client directory, load the Conda environment, and make sure the database is current:
@@ -31,7 +31,7 @@ npm run build
The server will be running on http://0.0.0.0:5000/
-## development
+## Development
Monitor the Javascript for changes (run in another window):
diff --git a/animism-align/cli/commands/peaks/parse.py b/animism-align/cli/commands/peaks/parse.py
index dc9a0a2..117ecfd 100644
--- a/animism-align/cli/commands/peaks/parse.py
+++ b/animism-align/cli/commands/peaks/parse.py
@@ -4,8 +4,6 @@ Extract peaks from an MP3 file.
import click
-from app.site.builder import build_site, build_file
-
@click.command()
@click.option('-i', '--input', 'fp_in', required=False,
help='Input file')
@@ -24,16 +22,17 @@ def cli(ctx, fp_in):
print(f"Loading {fp_in}")
y, sr = librosa.load(fp_in, sr=None)
- sr_10 = math.floor(sr / 10)
- steps = math.floor(y.shape[0] / sr_10)
+ sr_10 = math.ceil(sr / 10)
+ steps = math.ceil(y.shape[0] / sr_10)
- peaks = numpy.ndarray(steps * 2)
+ peaks = numpy.ndarray(steps)
for i in range(steps):
offset = i * sr_10
slice = y[offset:offset + sr_10]
- peaks[i * 2] = float('%.3f' % slice.min())
- peaks[i * 2 + 1] = float('%.3f' % slice.max())
+ peak = max(abs(slice.min()), slice.max())
+ peaks[i] = float('%.3f' % peak)
+ # peaks[i * 2 + 1] = float('%.3f' % slice.max())
with open(os.path.join(app_cfg.DIR_DATA_STORE, 'peaks.json'), 'w') as fp_out:
json.dump(peaks.tolist(), fp_out, separators=(',', ':'))
diff --git a/animism-align/environment.yml b/animism-align/environment.yml
index af838e2..3a28790 100644
--- a/animism-align/environment.yml
+++ b/animism-align/environment.yml
@@ -18,12 +18,15 @@ dependencies:
- tk=8.6.8=ha441bb4_0
- wheel=0.33.4=py37_0
- xz=5.2.4=h1de35cc_4
+ - zlib=1.2.11=h1de35cc_3
- pip:
- alembic==1.2.1
- amqp==2.5.0
- async-timeout==3.0.1
+ - audioread==2.1.8
- billiard==3.6.0.0
- celery==4.3.0
+ - cffi==1.14.0
- chardet==3.0.4
- click==7.0
- colorlog==4.0.2
@@ -35,6 +38,7 @@ dependencies:
- flask-classful==0.14.2
- flask-sqlalchemy==2.4.0
- flask-wtf==0.14.2
+ - idna==2.8
- imageio==2.5.0
- imutils==0.5.2
- infinity==1.4
@@ -42,35 +46,50 @@ dependencies:
- itsdangerous==1.1.0
- jinja2==2.10.1
- joblib==0.13.2
+ - kiwisolver==1.2.0
- kombu==4.6.3
+ - librosa==0.7.2
+ - llvmlite==0.32.1
- mako==1.1.0
- markdown==3.1.1
- markupsafe==1.1.1
- matplotlib==3.1.1
- monotonic==1.5
+ - networkx==2.4
+ - numba==0.43.0
+ - numpy==1.19.0
- pbr==5.4.3
- pdoc==0.3.2
- pillow==6.1.0
+ - pycparser==2.20
+ - pyparsing==2.4.7
- python-dateutil==2.8.0
- python-dotenv==0.10.3
+ - python-editor==1.0.4
- pytz==2019.2
+ - pywavelets==1.1.1
- pyyaml==5.1.2
- requests==2.22.0
+ - resampy==0.2.2
- scikit-image==0.15.0
+ - scikit-learn==0.23.1
- scipy==1.3.0
- simplejson==3.16.0
- six==1.12.0
+ - soundfile==0.10.3.post1
- sqlalchemy==1.3.6
- sqlalchemy-utc==0.10.0
- sqlalchemy-utils==0.34.1
- sqlparse==0.3.0
- tempita==0.5.2
+ - threadpoolctl==2.1.0
- tqdm==4.32.2
- urllib3==1.25.3
- validators==0.13.0
+ - vine==1.3.0
- werkzeug==0.15.5
- wtforms==2.2.1
- wtforms-alchemy==0.16.9
- wtforms-components==0.10.4
-prefix: /Users/user/anaconda/envs/swimmer
+prefix: /Users/user/miniconda3/envs/animism
diff --git a/animism-align/frontend/api/crud.reducer.js b/animism-align/frontend/api/crud.reducer.js
index 04ade91..38aa4f8 100644
--- a/animism-align/frontend/api/crud.reducer.js
+++ b/animism-align/frontend/api/crud.reducer.js
@@ -114,6 +114,7 @@ export const crudReducer = (type) => {
return {
...state,
update: action.data,
+ index: addToIndex(state.index, action.data.res, state.options.sort),
}
case crud_type.index_error:
return {
diff --git a/animism-align/frontend/views/align/align.css b/animism-align/frontend/views/align/align.css
index a956b79..799693c 100644
--- a/animism-align/frontend/views/align/align.css
+++ b/animism-align/frontend/views/align/align.css
@@ -116,12 +116,12 @@ canvas {
.annotationIndex {
width: 405px;
}
-.annotation {
+.annotationIndex .annotation {
position: absolute;
left: 5px;
max-width: 450px;
padding: 0.25rem 0.375rem;
- box-shadow: 2px 2px 4px rgba(0,0,0,0.5);
+ box-shadow: 0px 0px 4px rgba(0,0,0,0.7);
border-radius: 2px;
font-size: 12px;
cursor: pointer;
diff --git a/animism-align/frontend/views/align/components/annotations/annotation.form.js b/animism-align/frontend/views/align/components/annotations/annotation.form.js
index b62c36e..6972f93 100644
--- a/animism-align/frontend/views/align/components/annotations/annotation.form.js
+++ b/animism-align/frontend/views/align/components/annotations/annotation.form.js
@@ -22,6 +22,12 @@ class AnnotationForm extends Component {
this.handleSelect = this.handleSelect.bind(this)
this.handleKeyDown = this.handleKeyDown.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
+ this.textareaRef = React.createRef()
+ }
+ componentDidMount() {
+ if (this.textareaRef && this.textareaRef.current) {
+ this.textareaRef.current.focus()
+ }
}
handleKeyDown(e) {
if (e.keyCode === 27) { // escape
@@ -111,6 +117,7 @@ class AnnotationForm extends Component {
value={annotation.text}
onKeyDown={this.handleKeyDown}
onChange={this.handleChange}
+ ref={this.textareaRef}
/>
</div>
)
diff --git a/animism-align/frontend/views/align/components/annotations/annotation.index.js b/animism-align/frontend/views/align/components/annotations/annotation.index.js
index 7b562c2..09cb255 100644
--- a/animism-align/frontend/views/align/components/annotations/annotation.index.js
+++ b/animism-align/frontend/views/align/components/annotations/annotation.index.js
@@ -38,7 +38,7 @@ class AnnotationIndex extends Component {
const items = order.filter(id => {
const { start_ts: ts } = lookup[id]
return (timeMin < ts && ts < timeMax)
- }).map(id => lookup[id])
+ }).map(id => lookup[id]).reverse()
this.setState({ items })
}
handleClick(annotation) {
diff --git a/animism-align/frontend/views/align/components/timeline/waveform.component.js b/animism-align/frontend/views/align/components/timeline/waveform.component.js
index 128204a..0a118cf 100644
--- a/animism-align/frontend/views/align/components/timeline/waveform.component.js
+++ b/animism-align/frontend/views/align/components/timeline/waveform.component.js
@@ -45,7 +45,6 @@ class Waveform extends Component {
let secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 // 0.1 sec / step
let stepsPerPixel = ZOOM_STEPS[zoom] // 0.1 sec / step
- let indexesPerPixel = stepsPerPixel * 2
let widthTimeDuration = h * secondsPerPixel // secs per pixel
@@ -53,7 +52,7 @@ class Waveform extends Component {
let timeMax = Math.min(start_ts + widthTimeDuration, duration)
let timeWidth = timeMax - timeMin
- let stepMin = Math.floor(timeMin * 10 * 2)
+ let stepMin = Math.floor(timeMin * 10)
let pixelWidth = Math.ceil(timeWidth / secondsPerPixel)
let i = 0
@@ -62,17 +61,17 @@ class Waveform extends Component {
let origin = (1 - peaks[step]) * waveformPeak
let y
let peak
- // console.log(0 * indexesPerPixel + stepMin, pixelWidth * indexesPerPixel + stepMin)
+ // console.log(stepMin, pixelWidth * stepsPerPixel + stepMin)
ctx.beginPath()
ctx.moveTo(origin, 0)
for (i = 0; i < pixelWidth; i++) {
- step = i * indexesPerPixel + stepMin
+ step = i * stepsPerPixel + stepMin
peak = peaks[step]
y = (1 - peak) * waveformPeak
ctx.lineTo(y, i)
}
for (i = pixelWidth - 1; i > 0; i--) {
- step = i * indexesPerPixel + stepMin
+ step = i * stepsPerPixel + stepMin
peak = peaks[step]
y = (1 + peak) * waveformPeak
ctx.lineTo(y, i)
diff --git a/animism-align/frontend/views/align/containers/timeline.container.js b/animism-align/frontend/views/align/containers/timeline.container.js
index 23b9435..ceb9012 100644
--- a/animism-align/frontend/views/align/containers/timeline.container.js
+++ b/animism-align/frontend/views/align/containers/timeline.container.js
@@ -31,6 +31,12 @@ class Timeline extends Component {
componentWillUnmount() {
this.unbind()
}
+ shouldComponentUpdate(nextProps) {
+ return (
+ nextProps.timeline !== this.props.timeline ||
+ nextProps.annotation !== this.props.annotation
+ )
+ }
bind() {
document.addEventListener('keydown', this.handleKeydown)
}
@@ -41,6 +47,7 @@ class Timeline extends Component {
if (document.activeElement !== document.body) {
return
}
+ // console.log(e.keyCode)
if (e.shiftKey) {
switch (e.keyCode) {
case 187: // plus
@@ -56,6 +63,10 @@ class Timeline extends Component {
case 27: // escape
actions.align.hideAnnotationForm()
break
+ case 65: // A - add
+ e.preventDefault()
+ actions.align.showNewAnnotationForm(this.props.audio.play_ts, this.props.text)
+ break
case 32: // spacebar
actions.audio.toggle()
break
@@ -70,12 +81,13 @@ class Timeline extends Component {
}
handleWheel(e) {
let { start_ts, zoom, duration } = this.props.timeline
+ let { deltaY } = e
let secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 // 0.1 sec / step
let widthTimeDuration = window.innerHeight * secondsPerPixel // secs per pixel
-
- start_ts = clamp(start_ts + e.deltaY * ZOOM_STEPS[zoom], 0, Math.max(0, duration - widthTimeDuration / 2))
+ start_ts += (deltaY / 2) * ZOOM_STEPS[zoom]
+ start_ts = clamp(start_ts, 0, Math.max(0, duration - widthTimeDuration / 2))
if (e.shiftKey) {
- if (Math.abs(e.deltaY) < 2) return
+ if (Math.abs(deltaY) < 2) return
if (e.deltaY > 0) {
actions.align.throttledSetZoom(this.props.timeline.zoom + 1)
} else {
@@ -93,10 +105,10 @@ class Timeline extends Component {
}
handleClick(e) {
const play_ts = positionToTime(e.pageY, this.props.timeline)
- if (e.pageX > WAVEFORM_SIZE * 0.67) {
- actions.align.showNewAnnotationForm(play_ts, this.props.text)
- } else {
+ if (e.pageX < WAVEFORM_SIZE * 0.67) {
actions.audio.seek(play_ts)
+ } else {
+ actions.align.showNewAnnotationForm(play_ts, this.props.text)
}
}
render() {
@@ -122,6 +134,7 @@ class Timeline extends Component {
const mapStateToProps = state => ({
timeline: state.align.timeline,
annotation: state.align.annotation,
+ audio: state.audio,
text: state.site.text,
})