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

preview.js 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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, heightFactor;
  50. if (height > width) {
  51. widthFactor = 360 / width;
  52. heightFactor = 640 / height;
  53. } else {
  54. widthFactor = 640 / width;
  55. heightFactor = 360 / height;
  56. }
  57. var factor = Math.min(widthFactor, heightFactor);
  58. d3.select("canvas")
  59. .attr("width", factor * width)
  60. .attr("height", factor * height);
  61. d3.select("#canvas")
  62. .style("width", (factor * width) + "px");
  63. d3.select("video")
  64. .attr("height", widthFactor * height);
  65. d3.select("#video")
  66. .attr("height", (widthFactor * height) + "px");
  67. context.setTransform(factor, 0, 0, factor, 0, 0);
  68. }
  69. function redraw() {
  70. resize(theme.width, theme.height);
  71. video.kill();
  72. var renderer = getRenderer(theme);
  73. renderer.backgroundImage(theme.backgroundImageFile || null);
  74. renderer.drawFrame(context, {
  75. caption: caption,
  76. waveform: sampleWave,
  77. frame: 0
  78. });
  79. if (location.pathname === "/theme") {
  80. const tf = (theme.noPattern === undefined) ? false : theme.noPattern;
  81. d3.select("#chkNoPattern").property("checked", tf);
  82. }
  83. }
  84. function loadAudio(f, cb) {
  85. d3.queue()
  86. .defer(getWaveform, f)
  87. .defer(audio.src, f)
  88. .await(function(err, data){
  89. if (err) {
  90. return cb(err);
  91. }
  92. file = f;
  93. minimap.redraw(data.peaks);
  94. cb(err);
  95. });
  96. }
  97. function loadNewTheme(f, cb) {
  98. d3.queue()
  99. .await(function(err, data){
  100. if (err) {
  101. return cb(err);
  102. }
  103. newTheme = f;
  104. cb(err);
  105. });
  106. }
  107. function loadSubtitle(f, cb) {
  108. d3.queue()
  109. .await(function(err, data){
  110. if (err) {
  111. return cb(err);
  112. }
  113. subtitle = f;
  114. cb(err);
  115. });
  116. }
  117. module.exports = {
  118. caption: _caption,
  119. theme: _theme,
  120. file: _file,
  121. selection: _selection,
  122. loadAudio: loadAudio,
  123. newTheme: _newTheme,
  124. newCaption: _newCaption,
  125. loadNewTheme: loadNewTheme,
  126. subtitle: _subtitle,
  127. loadSubtitle: loadSubtitle
  128. };