Turn audio into a shareable video. forked from nypublicradio/audiogram

preview.js 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. var d3 = require("d3"),
  2. audio = require("./audio.js"),
  3. video = require("./video.js"),
  4. minimap = require("./minimap.js"),
  5. sampleWave = require("./sample-wave.js"),
  6. getRenderer = require("../renderer/"),
  7. getWaveform = require("./waveform.js");
  8. var context = d3.select("canvas").node().getContext("2d");
  9. var theme,
  10. caption,
  11. file,
  12. selection,
  13. newTheme,
  14. newCaption;
  15. function _file(_) {
  16. return arguments.length ? (file = _) : file;
  17. }
  18. function _theme(_) {
  19. return arguments.length ? (theme = _, redraw()) : theme;
  20. }
  21. function _caption(_) {
  22. return arguments.length ? (caption = _, redraw()) : caption;
  23. }
  24. function _selection(_) {
  25. return arguments.length ? (selection = _) : selection;
  26. }
  27. function _newTheme(_) {
  28. return arguments.length ? (newTheme = _) : newTheme;
  29. }
  30. function _newCaption(_) {
  31. return arguments.length ? (newCaption = _) : newCaption;
  32. }
  33. minimap.onBrush(function(extent){
  34. var duration = audio.duration();
  35. selection = {
  36. duration: duration * (extent[1] - extent[0]),
  37. start: extent[0] ? extent[0] * duration : null,
  38. end: extent[1] < 1 ? extent[1] * duration : null
  39. };
  40. d3.select("#duration strong").text(Math.round(10 * selection.duration) / 10)
  41. .classed("red", theme && theme.maxDuration && theme.maxDuration < selection.duration);
  42. });
  43. // Resize video and preview canvas to maintain aspect ratio
  44. function resize(width, height) {
  45. var widthFactor = 640 / width,
  46. heightFactor = 360 / height,
  47. factor = Math.min(widthFactor, heightFactor);
  48. d3.select("canvas")
  49. .attr("width", factor * width)
  50. .attr("height", factor * height);
  51. d3.select("#canvas")
  52. .style("width", (factor * width) + "px");
  53. d3.select("video")
  54. .attr("height", widthFactor * height);
  55. d3.select("#video")
  56. .attr("height", (widthFactor * height) + "px");
  57. context.setTransform(factor, 0, 0, factor, 0, 0);
  58. }
  59. function redraw() {
  60. resize(theme.width, theme.height);
  61. video.kill();
  62. var renderer = getRenderer(theme);
  63. renderer.backgroundImage(theme.backgroundImageFile || null);
  64. renderer.drawFrame(context, {
  65. caption: caption,
  66. waveform: sampleWave,
  67. frame: 0
  68. });
  69. }
  70. function loadAudio(f, cb) {
  71. d3.queue()
  72. .defer(getWaveform, f)
  73. .defer(audio.src, f)
  74. .await(function(err, data){
  75. if (err) {
  76. return cb(err);
  77. }
  78. file = f;
  79. minimap.redraw(data.peaks);
  80. cb(err);
  81. });
  82. }
  83. function loadNewTheme(f, cb) {
  84. d3.queue()
  85. .await(function(err, data){
  86. if (err) {
  87. return cb(err);
  88. }
  89. newTheme = f;
  90. cb(err);
  91. });
  92. }
  93. module.exports = {
  94. caption: _caption,
  95. theme: _theme,
  96. file: _file,
  97. selection: _selection,
  98. loadAudio: loadAudio,
  99. newTheme: _newTheme,
  100. newCaption: _newCaption,
  101. loadNewTheme: loadNewTheme
  102. };