Skip to content

Commit 69a5be2

Browse files
committed
initial commit
0 parents  commit 69a5be2

File tree

19 files changed

+7746
-0
lines changed

19 files changed

+7746
-0
lines changed

.gitignore

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
.DS_Store
2+
3+
# Logs
4+
logs
5+
*.log
6+
npm-debug.log*
7+
8+
# Runtime data
9+
pids
10+
*.pid
11+
*.seed
12+
13+
# Directory for instrumented libs generated by jscoverage/JSCover
14+
lib-cov
15+
16+
# Coverage directory used by tools like istanbul
17+
coverage
18+
19+
# nyc test coverage
20+
.nyc_output
21+
22+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
23+
.grunt
24+
25+
# node-waf configuration
26+
.lock-wscript
27+
28+
# Compiled binary addons (http://nodejs.org/api/addons.html)
29+
build/Release
30+
31+
# Dependency directories
32+
node_modules
33+
jspm_packages
34+
35+
# Optional npm cache directory
36+
.npm
37+
38+
# Optional REPL history
39+
.node_repl_history

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 Donald Hanson
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Code Keyframes
2+
3+
A browser based tool for running JavaScript code at specific frames of an audio track. This is useful for creating interactive music videos, making subtitles, or anything else where audiovisual synchronization is required.
4+
5+
## How-To
6+
7+
1. Include the js file and the css file from the repository. (Links coming soon)
8+
2. Initialize an instance of CodeKeyframes:
9+
10+
```javascript
11+
var ckf = new CodeKeyframes({
12+
audioPath: 'audio/yourMusic.mp3',
13+
editorOpen: true,
14+
waveColor: '#3AEAD2',
15+
progressColor: '#0c9fa7',
16+
bgColor: '#222',
17+
keyframes:[] // paste in after exporting keyframes
18+
})
19+
```
20+
21+
3. Write your keyframes in the browser. The tool is keyboard controlled. See controls below.
22+
23+
4. Click EXPORT KEYFRAMES and paste the resulting code as your keyframes array from when you initialized the instance. This saves your keyframes out of localStorage and into a variable.
24+
25+
5. Change `editorOpen` to `false` and your keyframes will still run while only showing the audio waveform without the editor.
26+
27+
## Controls
28+
29+
Make sure you click the waveform before using keyboard controls. This choice was to avoid adding event listeners to the entire page, to prevent overlap with any other controls that you might use on the page.
30+
31+
`Left & Right` : Move playhead
32+
`Shift + Left or Right ` : Nudge playhead
33+
`Up & Down` : Zoom waveform
34+
`Space` : Play / Pause
35+
`Enter` : Add keyframe
36+
`Page Up & Page Down` : Jump between keyframes
37+
38+
## Acknowledgements
39+
40+
This tool relies hugely on [Wavesurfer](https://wavesurfer-js.org/). Big thanks to [katspaugh](https://github.com/katspaugh/wavesurfer.js) for their work on it.
41+
42+
The repository build structure is based on [Net Art Starter](https://github.com/gridwalk/net-art-starter) by me Donald Hanson. You can learn more about the structure and use it yourself.

dist/audio/KIYOKO.mp3

4.68 MB
Binary file not shown.

dist/img/poster.png

20 KB
Loading

dist/index.html

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<title>Project Title</title>
6+
<link rel="stylesheet" href="style.css">
7+
<meta name="viewport" content="width=device-width">
8+
9+
<!-- Open Graph tags for social media -->
10+
<meta property="og:title" content="Project Title">
11+
<meta property="og:description" content="Project description">
12+
<meta property="og:image" content="http://project-url.com/img/poster.jpg">
13+
<meta property="og:url" content="http://project-url.com">
14+
<meta name="twitter:card" content="summary_large_image">
15+
<meta property="og:site_name" content="Site Title">
16+
17+
</head>
18+
19+
<body>
20+
21+
<div id="example"></div>
22+
23+
<script src='main.js'></script>
24+
25+
<script>
26+
var ckf = new CodeKeyFrames({
27+
audioPath: 'audio/KIYOKO.mp3',
28+
editorOpen: true,
29+
waveColor: '#3AEAD2',
30+
progressColor: '#0c9fa7',
31+
bgColor: '#222',
32+
keyframes:[{"start":0,"end":0.1,"data":{"code":"console.log('boom')"}},{"start":2.6999999999999997,"end":2.8,"data":{"code":"console.log('boom2')"}},{"start":5.3623202124984966,"end":5.462320212498496,"data":{"code":"console.log('boom3')"}},{"start":8.080544217687077,"end":8.180544217687077,"data":{"code":"console.log('boom4')"}},{"start":10.686984126984129,"end":10.786984126984128,"data":{"code":"console.log('boom')"}},{"start":13.415328798185946,"end":13.515328798185946,"data":{"code":"console.log('boom4')"}},{"start":16.074013605442182,"end":16.174013605442184,"data":{"code":"console.log('booms3')"}},{"start":18.726893424036284,"end":18.826893424036285,"data":{"code":"console.log('boodsfdsm3')"}},{"start":21.420408163265314,"end":21.520408163265316,"data":{"code":"console.log('boodsfm3')"}}]
33+
})
34+
</script>
35+
36+
<script>
37+
// This is the LiveReload snippet that tells the page to refresh when you make a change.
38+
// You can delete if before uploading your finished site.
39+
document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] +
40+
':35729/livereload.js?snipver=1"></' + 'script>')
41+
</script>
42+
43+
</body>
44+
</html>

dist/main.js

Lines changed: 451 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/style.css

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gulpfile.js

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
var http = require('http') // node core module to serve data
2+
var gulp = require('gulp') // gulp task runner
3+
var watch = require('gulp-watch') // watch for files that change
4+
var sass = require('gulp-sass') // compiles sass
5+
var autoprefixer = require('gulp-autoprefixer') // applies CSS vendor prefixes
6+
var rename = require('gulp-rename') // renames files
7+
var livereload = require('gulp-livereload') // reload browser when files change
8+
var concat = require('gulp-concat') // concatenate scripts
9+
var serveStatic = require('serve-static') // serves static files
10+
var finalhandler = require('finalhandler') // standardizes server response
11+
var opn = require('opn') // opens the browser when we gulp
12+
var jshint = require('gulp-jshint') // catches errors in javascript
13+
var stylish = require('jshint-stylish') // makes lint errors look nicer
14+
var plumber = require('gulp-plumber') // keeps pipes working even when error var ppens
15+
var notify = require('gulp-notify') // system notification when error happevar
16+
17+
// paths to files that are used in the project
18+
var paths = {
19+
styles: './src/scss/**/*',
20+
scripts: {
21+
vendor: './src/js/vendor/**/*',
22+
app: './src/js/app/**/*',
23+
},
24+
images: './src/img/**/*',
25+
pages: './src/html/**/*',
26+
dist: './dist'
27+
}
28+
29+
// these tasks execute in order when you run gulp
30+
gulp.task('default', ['styles', 'scripts', 'images', 'html', 'serve', 'watch', 'livereload-listen', 'open'])
31+
32+
33+
/*
34+
35+
███████╗████████╗██╗ ██╗██╗ ███████╗███████╗
36+
██╔════╝╚══██╔══╝╚██╗ ██╔╝██║ ██╔════╝██╔════╝
37+
███████╗ ██║ ╚████╔╝ ██║ █████╗ ███████╗
38+
╚════██║ ██║ ╚██╔╝ ██║ ██╔══╝ ╚════██║
39+
███████║ ██║ ██║ ███████╗███████╗███████║
40+
╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚══════╝
41+
42+
*****************************************************/
43+
44+
// compiles scss files into one, starting from style.scss
45+
// sass searches style.scss for import statements and includes those files
46+
// also minifies resulting css and auto-prefixes for browser compatibility
47+
48+
gulp.task('styles', [], function(){
49+
50+
// show notification on scss error
51+
52+
var scssError = function(err){
53+
notify.onError({
54+
title: err.relativePath,
55+
subtitle: 'Line '+err.line,
56+
message: '<%= error.messageOriginal %>'
57+
})(err)
58+
this.emit('end')
59+
}
60+
61+
// do the scss compilation
62+
63+
gulp.src('./src/scss/style.scss')
64+
.pipe(plumber({
65+
errorHandler: scssError
66+
}))
67+
.pipe(sass({outputStyle: 'compressed'}))
68+
.pipe(autoprefixer({
69+
browsers: ['last 2 versions'],
70+
cascade: false
71+
}))
72+
.pipe(rename('style.css'))
73+
.pipe(gulp.dest(paths.dist))
74+
.pipe(livereload())
75+
})
76+
77+
78+
/*
79+
80+
███████╗ ██████╗██████╗ ██╗██████╗ ████████╗███████╗
81+
██╔════╝██╔════╝██╔══██╗██║██╔══██╗╚══██╔══╝██╔════╝
82+
███████╗██║ ██████╔╝██║██████╔╝ ██║ ███████╗
83+
╚════██║██║ ██╔══██╗██║██╔═══╝ ██║ ╚════██║
84+
███████║╚██████╗██║ ██║██║██║ ██║ ███████║
85+
╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ╚══════╝
86+
87+
********************************************************/
88+
89+
// compiles all JS files into one file
90+
// first concatenates js in vendor folder, then js in app folder
91+
92+
gulp.task('scripts', ['lint'], function(){
93+
return gulp.src([paths.scripts.vendor,paths.scripts.app])
94+
.pipe(concat('main.js'))
95+
.pipe(gulp.dest(paths.dist))
96+
.pipe(livereload())
97+
})
98+
99+
// shows notification on js error
100+
101+
gulp.task('lint',function(){
102+
return gulp.src(paths.scripts.app)
103+
.pipe(plumber())
104+
.pipe(jshint({
105+
'esversion': 6,
106+
'asi':true, // allows missing semicolons
107+
'sub':true // allows bracket notation of array items
108+
}))
109+
.pipe(jshint.reporter('jshint-stylish'))
110+
.pipe(notify(function (file) { // Use gulp-notify as jshint reporter
111+
if (file.jshint.success) {
112+
return false // Don't show something if success
113+
}
114+
var errors = file.jshint.results.map(function (data) {
115+
if (data.error) {
116+
return "(" + data.error.line + ':' + data.error.character + ') ' + data.error.reason
117+
}
118+
}).join("\n")
119+
return file.relative + " (" + file.jshint.results.length + " errors)\n" + errors
120+
}))
121+
})
122+
123+
/*
124+
125+
██╗ ██╗████████╗███╗ ███╗██╗
126+
██║ ██║╚══██╔══╝████╗ ████║██║
127+
███████║ ██║ ██╔████╔██║██║
128+
██╔══██║ ██║ ██║╚██╔╝██║██║
129+
██║ ██║ ██║ ██║ ╚═╝ ██║███████╗
130+
╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝
131+
132+
*************************************/
133+
134+
// just copies HTML to the dist folder, no compilation step
135+
// this exists to gain the benefit of livereload when editing pages
136+
137+
gulp.task('html',['styles','images'], function () {
138+
return gulp.src(paths.pages)
139+
.pipe(gulp.dest(paths.dist))
140+
.pipe(livereload())
141+
})
142+
143+
/*
144+
145+
██╗ ███╗ ███╗ █████╗ ██████╗ ███████╗ ███████╗
146+
██║ ████╗ ████║ ██╔══██╗ ██╔════╝ ██╔════╝ ██╔════╝
147+
██║ ██╔████╔██║ ███████║ ██║ ███╗ █████╗ ███████╗
148+
██║ ██║╚██╔╝██║ ██╔══██║ ██║ ██║ ██╔══╝ ╚════██║
149+
██║ ██║ ╚═╝ ██║ ██║ ██║ ╚██████╔╝ ███████╗ ███████║
150+
╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚══════╝
151+
152+
****************************************************/
153+
154+
// just copies images to the dist folder, no processing
155+
// this exists to gain the benefit of livereload when changing images
156+
157+
gulp.task('images', function(){
158+
return gulp.src(paths.images,{base:'./src/img/'})
159+
.pipe(gulp.dest(paths.dist+'/img'))
160+
.pipe(livereload())
161+
})
162+
163+
164+
/*
165+
166+
███████╗███████╗██████╗ ██╗ ██╗███████╗██████╗
167+
██╔════╝██╔════╝██╔══██╗██║ ██║██╔════╝██╔══██╗
168+
███████╗█████╗ ██████╔╝██║ ██║█████╗ ██████╔╝
169+
╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██╔══╝ ██╔══██╗
170+
███████║███████╗██║ ██║ ╚████╔╝ ███████╗██║ ██║
171+
╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝
172+
173+
****************************************************/
174+
175+
// running gulp will start a little server in the dist folder
176+
177+
gulp.task('serve',['html'], function() {
178+
179+
// Serve up dist folder
180+
var serve = serveStatic(paths.dist)
181+
182+
// Start server
183+
var server = http.createServer(function(req, res){
184+
var done = finalhandler(req, res)
185+
serve(req, res, done)
186+
})
187+
188+
// Listen for requests on port 3000
189+
// http://localhost:3000
190+
server.listen(3000)
191+
})
192+
193+
// opens browser to the page
194+
gulp.task('open',['serve'], function(){
195+
opn('http://localhost:3000')
196+
})
197+
198+
// tell livereload to start listening for changed files
199+
// when a file changes the browser reloads itself
200+
gulp.task('livereload-listen', function(){
201+
livereload.listen()
202+
})
203+
204+
205+
/*
206+
207+
██╗ ██╗ █████╗ ████████╗ ██████╗██╗ ██╗
208+
██║ ██║██╔══██╗╚══██╔══╝██╔════╝██║ ██║
209+
██║ █╗ ██║███████║ ██║ ██║ ███████║
210+
██║███╗██║██╔══██║ ██║ ██║ ██╔══██║
211+
╚███╔███╔╝██║ ██║ ██║ ╚██████╗██║ ██║
212+
╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
213+
214+
**********************************************/
215+
216+
// gulp watches the filesystem for changes, then compiles the according files
217+
218+
gulp.task('watch',['serve'], function(){
219+
220+
watch(paths.styles,function(){
221+
gulp.start('styles')
222+
})
223+
224+
watch([paths.scripts.app,paths.scripts.vendor],function(){
225+
gulp.start('scripts')
226+
})
227+
228+
watch(paths.pages,function(){
229+
gulp.start('html')
230+
})
231+
232+
watch(paths.images,function(){
233+
gulp.start('images')
234+
})
235+
236+
})

0 commit comments

Comments
 (0)