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

preview.js 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. subtitle;
  16. function _file(_) {
  17. return arguments.length ? (file = _) : file;
  18. }
  19. function _theme(_) {
  20. return arguments.length ? (theme = _, redraw()) : theme;
  21. }
  22. function _caption(_) {
  23. return arguments.length ? (caption = _, redraw()) : caption;
  24. }
  25. function _selection(_) {
  26. return arguments.length ? (selection = _) : selection;
  27. }
  28. function _newTheme(_) {
  29. return arguments.length ? (newTheme = _) : newTheme;
  30. }
  31. function _newCaption(_) {
  32. return arguments.length ? (newCaption = _) : newCaption;
  33. }
  34. function _subtitle(_) {
  35. return arguments.length ? (subtitle = _) : subtitle;
  36. }
  37. minimap.onBrush(function(extent){
  38. var duration = audio.duration();
  39. selection = {
  40. duration: duration * (extent[1] - extent[0]),
  41. start: extent[0] ? extent[0] * duration : null,
  42. end: extent[1] < 1 ? extent[1] * duration : null
  43. };
  44. d3.select("#duration strong").text(Math.round(10 * selection.duration) / 10)
  45. .classed("red", theme && theme.maxDuration && theme.maxDuration < selection.duration);
  46. });
  47. // Resize video and preview canvas to maintain aspect ratio
  48. function resize(width, height) {
  49. var widthFactor = 640 / width,
  50. heightFactor = 360 / height,
  51. factor = Math.min(widthFactor, heightFactor);
  52. d3.select("canvas")
  53. .attr("width", factor * width)
  54. .attr("height", factor * height);
  55. d3.select("#canvas")
  56. .style("width", (factor * width) + "px");
  57. d3.select("video")
  58. .attr("height", widthFactor * height);
  59. d3.select("#video")
  60. .attr("height", (widthFactor * height) + "px");
  61. context.setTransform(factor, 0, 0, factor, 0, 0);
  62. }
  63. function redraw() {
  64. resize(theme.width, theme.height);
  65. video.kill();
  66. var renderer = getRenderer(theme);
  67. renderer.backgroundImage(theme.backgroundImageFile || null);
  68. renderer.drawFrame(context, {
  69. caption: caption,
  70. waveform: sampleWave,
  71. frame: 0
  72. });
  73. if (location.pathname === "/theme") {
  74. const tf = (theme.noPattern === undefined) ? false : theme.noPattern;
  75. d3.select("#chkNoPattern").property("checked", tf);
  76. }
  77. }
  78. function loadAudio(f, cb) {
  79. d3.queue()
  80. .defer(getWaveform, f)
  81. .defer(audio.src, f)
  82. .await(function(err, data){
  83. if (err) {
  84. return cb(err);
  85. }
  86. file = f;
  87. minimap.redraw(data.peaks);
  88. cb(err);
  89. });
  90. }
  91. function loadNewTheme(f, cb) {
  92. d3.queue()
  93. .await(function(err, data){
  94. if (err) {
  95. return cb(err);
  96. }
  97. newTheme = f;
  98. cb(err);
  99. });
  100. }
  101. function loadSubtitle(f, cb) {
  102. d3.queue()
  103. .await(function(err, data){
  104. if (err) {
  105. return cb(err);
  106. }
  107. subtitle = f;
  108. cb(err);
  109. });
  110. }
  111. module.exports = {
  112. caption: _caption,
  113. theme: _theme,
  114. file: _file,
  115. selection: _selection,
  116. loadAudio: loadAudio,
  117. newTheme: _newTheme,
  118. newCaption: _newCaption,
  119. loadNewTheme: loadNewTheme,
  120. subtitle: _subtitle,
  121. loadSubtitle: loadSubtitle
  122. };