Youtube music and video downloader

links.js 3.1KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import { Meteor } from 'meteor/meteor';
  2. import { Mongo } from 'meteor/mongo';
  3. import { check, Match } from 'meteor/check';
  4. export const Converted = new Mongo.Collection('links');
  5. const YTExp = /http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-_]*)/;
  6. if (Meteor.isServer) {
  7. Meteor.publish('links', function linksPublication() {
  8. return Converted.find();
  9. });
  10. }
  11. const convert = (url, filename, id) => {
  12. if (Meteor.isServer) {
  13. console.log('Converting ...');
  14. const fs = Meteor.npmRequire("fs");
  15. const ytdl = Meteor.npmRequire('ytdl-core');
  16. const path = Meteor.npmRequire('path');
  17. const ffmpeg = Meteor.npmRequire('fluent-ffmpeg');
  18. const filePath = path.resolve('/home/kod3/projects/SoundWave/uploaded/', filename)
  19. const videoPath = filePath + '.mp4';
  20. const audioPath = filePath + '.mp3';
  21. ytdl.getInfo(url, {}, Meteor.bindEnvironment((err, info) => {
  22. console.info(info ? 'ok' : 'ko');
  23. if (err) {
  24. console.log(url);
  25. console.error(err);
  26. Converted.update({ _id: id }, { $set: { error: 'Video is unreachable' } });
  27. } else {
  28. const totalSeconds = info ? info.length_seconds : 0;
  29. const dl = ytdl(url);
  30. dl.pipe(fs.createWriteStream(videoPath));
  31. ffmpeg(dl)
  32. .noVideo()
  33. .on('end', Meteor.bindEnvironment(() => {
  34. Converted.update({ _id: id }, { $set: { audio: audioPath, audio_progress: 100 } });
  35. }))
  36. .on('progress', Meteor.bindEnvironment((params) => {
  37. const time = moment(new Date(...[0, 0, 0, ...params.timemark.split(':')]));
  38. const seconds = time.hours() * 3600 + time.minutes() * 60 + time.seconds();
  39. let percent = ((seconds / totalSeconds) * 100).toFixed(0);
  40. Converted.update({ _id: id }, { $set: { audio_progress: percent } });
  41. }))
  42. .on('error', (err) => { console.error('MP3 encoding error: ' + err.message); })
  43. .format('mp3')
  44. .output(fs.createWriteStream(audioPath))
  45. .run();
  46. dl.on('info', (info, format) => console.log);
  47. dl.on('response', Meteor.bindEnvironment((res) => {
  48. const totalSize = res.headers['content-length'];
  49. let dataRead = 0;
  50. res.on('data', Meteor.bindEnvironment((data) => {
  51. dataRead += data.length;
  52. let percent = dataRead / totalSize;
  53. Converted.update({ _id: id }, { $set: { video_progress: (percent * 100).toFixed(0) } });
  54. }));
  55. res.on('end', Meteor.bindEnvironment(() => {
  56. Converted.update({ _id: id }, { $set: { video: videoPath, video_progress: 100 } });
  57. }));
  58. res.on('error', (err) => { console.error('Error: ' + err.message) });
  59. }));
  60. }
  61. }));
  62. } else return false;
  63. };
  64. Meteor.methods({
  65. 'links.add'({video, type}) {
  66. check(video.url, Match.Where(url => YTExp.test(url)));
  67. check(type, Match.Where(t => ['audio'].includes(t)));
  68. let converted = Converted.findOne({
  69. url: video.url
  70. });
  71. if (!converted) {
  72. const filename = video.title.replace(/ /g, '_');
  73. var inserted_id = Converted.insert({
  74. id: video.id,
  75. url: video.url,
  76. title: video.title,
  77. video: '',
  78. video_progress: 0,
  79. audio: '',
  80. audio_progress: 0,
  81. createdAt: new Date()
  82. });
  83. convert(video.url, filename, inserted_id);
  84. }
  85. },
  86. });