Skip to content

Commit

Permalink
replace web-audio-api to ffmpeg
Browse files Browse the repository at this point in the history
  • Loading branch information
trquoccuong committed Feb 9, 2017
1 parent f951924 commit 282e539
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 67 deletions.
188 changes: 124 additions & 64 deletions lib/render.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
var AudioContext = require('web-audio-api').AudioContext
var fs = require('fs')
var spawn = require('child_process').spawn
var Canvas = require('canvas')

var defaultSetting = {
Expand All @@ -16,9 +15,64 @@ var defaultSetting = {
baselineWidth: 0,
baselineColor: 'white'
}
//https://github.com/jhurliman/node-pcm
function getPcmData (filename, options, sampleCallback, endCallback) {
var outputStr = ''
var oddByte = null
var channel = 0
var gotData = false

options = options || {}
var channels = 2
if (typeof options.stereo !== 'undefined') {
channels = (options.stereo) ? 2 : 1
}
var sampleRate = 44100
if (typeof options.sampleRate !== 'undefined') {
sampleRate = options.sampleRate
}

var ffmpeg = spawn('ffmpeg', ['-i', filename, '-f', 's16le', '-ac', channels,
'-acodec', 'pcm_s16le', '-ar', sampleRate, '-y', 'pipe:1'])

ffmpeg.stdout.on('data', function (data) {
gotData = true

var value
var i = 0
var dataLen = data.length

// If there is a leftover byte from the previous block, combine it with the
// first byte from this block
if (oddByte !== null) {
value = ((data.readInt8(i++, true) << 8) | oddByte) / 32767.0
sampleCallback(value, channel)
channel = ++channel % 2
}

for (; i < dataLen; i += 2) {
value = data.readInt16LE(i, true) / 32767.0
sampleCallback(value, channel)
channel = ++channel % 2
}

oddByte = (i < dataLen) ? data.readUInt8(i, true) : null
})

ffmpeg.stderr.on('data', function (data) {
outputStr += data.toString()
})

ffmpeg.stderr.on('end', function () {
if (gotData) {
endCallback(null, outputStr)
} else {
endCallback(outputStr, null)
}
})
}

module.exports = function render (url, options, cb) {
var audioContext = new AudioContext()
if (typeof options === 'function') {
cb = options
options = {}
Expand All @@ -35,70 +89,76 @@ module.exports = function render (url, options, cb) {

var canvas = new Canvas(options.width, options.height)
var canvasContext = canvas.getContext('2d')
fs.readFile(url, function (err, buffer) {
if (err) return cb(err)

audioContext.decodeAudioData(buffer, function (result) {
var data = result.getChannelData(0)
var step = Math.floor(data.length / options.width)
var ratio = options.baseline / options.height
var vals = []

canvasContext.fillStyle = options.backgroundColor
canvasContext.fillRect(0, 0, options.width, options.height)

canvasContext.fillStyle = options.waveColor

for (var i = 0; i < options.width; i += options.barWidth) {
var position = i * step
var sum = 0.0
for (var j = position; j <= (position + step) - 1; j++) {
sum += Math.pow(data[j], 2)
}
vals.push(Math.sqrt(sum / data.length) * 10000)
var data = []

getPcmData(url, null, function (sample, channel) {
if (channel === 0) {
data.push(sample)
}
}, function (err) {

if (err) {
return cb(err)
}

var step = Math.floor(data.length / options.width)
var ratio = options.baseline / options.height
var vals = []

canvasContext.fillStyle = options.backgroundColor
canvasContext.fillRect(0, 0, options.width, options.height)

canvasContext.fillStyle = options.waveColor

for (var i = 0; i < options.width; i += options.barWidth) {
var position = i * step
var sum = 0.0
for (var j = position; j <= (position + step) - 1; j++) {
sum += Math.pow(data[j], 2)
}
vals.push(Math.sqrt(sum / data.length) * 10000)
}

var maxValue = Math.max.apply(null, vals)

var maxValue = Math.max.apply(null, vals)

vals.forEach(function (val, index) {
var scale = options.height / maxValue
val *= scale
var w = options.barWidth
if (options.barGap !== 0) {
w *= Math.abs(1 - options.barGap)
}
var x = index * options.barWidth + (w / 2)

var lowerHeight = val * ratio

if (lowerHeight < options.padding) {
lowerHeight = 1
} else {
lowerHeight -= options.padding
}

var upperHeight = val * (1 - ratio)

if (upperHeight < options.padding) {
upperHeight = 1
} else {
upperHeight -= options.padding
}

if (options.waveAlpha < 1) {
canvasContext.clearRect(x, options.baseline, w, upperHeight)
canvasContext.clearRect(x, options.baseline, w, -lowerHeight)
canvasContext.globalAlpha = options.waveAlpha
}
canvasContext.fillRect(x, options.baseline, w, upperHeight)
canvasContext.fillRect(x, options.baseline, w, -lowerHeight)
})

if (options.baselineWidth >= 1) {
canvasContext.fillStyle = options.baselineColor
canvasContext.fillRect(0, options.baseline - (options.baselineWidth / 2), options.width, options.baselineWidth)
vals.forEach(function (val, index) {
var scale = options.height / maxValue
val *= scale
var w = options.barWidth
if (options.barGap !== 0) {
w *= Math.abs(1 - options.barGap)
}
cb(null, canvas.toBuffer())
var x = index * options.barWidth + (w / 2)

var lowerHeight = val * ratio

if (lowerHeight < options.padding) {
lowerHeight = 1
} else {
lowerHeight -= options.padding
}

var upperHeight = val * (1 - ratio)

if (upperHeight < options.padding) {
upperHeight = 1
} else {
upperHeight -= options.padding
}

if (options.waveAlpha < 1) {
canvasContext.clearRect(x, options.baseline, w, upperHeight)
canvasContext.clearRect(x, options.baseline, w, -lowerHeight)
canvasContext.globalAlpha = options.waveAlpha
}
canvasContext.fillRect(x, options.baseline, w, upperHeight)
canvasContext.fillRect(x, options.baseline, w, -lowerHeight)
})

if (options.baselineWidth >= 1) {
canvasContext.fillStyle = options.baselineColor
canvasContext.fillRect(0, options.baseline - (options.baselineWidth / 2), options.width, options.baselineWidth)
}
cb(null, canvas.toBuffer())
})
}
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "node-wave",
"version": "0.0.3",
"version": "0.0.4",
"description": "Render waveform image like SoundCloud",
"main": "index.js",
"scripts": {
Expand All @@ -19,8 +19,7 @@
"url": "git+https://github.com/trquoccuong/node-wave.git"
},
"dependencies": {
"canvas": "^1.6.2",
"web-audio-api": "^0.2.2"
"canvas": "^1.6.2"
},
"devDependencies": {
"mocha": "^3.2.0",
Expand Down
Binary file removed test/out.png
Binary file not shown.

0 comments on commit 282e539

Please sign in to comment.