16

I am working to design a system which does the following:

  1. User uploads a video, JS code finds the length of the video.

  2. Performs HTTP calls to an already-existing service to retrieve an audio track of the same length.

  3. Synchronize and combine the audio and video (which are the exact same length). The best thing I could think to do is to play them both at the same time (entirely doable with HTML5), but I want to be able to have a user download a combined file, or be able to say... upload it to YouTube through their API.

I have been doing lots of googling, and so far have not found any services or code which might be able to do this.

I am familiar with JavaScript, Ruby on Rails, HTML, CSS, jQuery, and both AngularJS and Backbone.js. If a solution exists in one of those languages, or perhaps something I can access through HTTP, that would be wonderful.

Buddy Lamers
  • 239
  • 1
  • 2
  • 6
  • 1
    To define: all I want to be able to do is add an audio track to the video, replacing the existing one (if any). – Buddy Lamers Mar 06 '15 at 00:19
  • 1
    My post was downvoted for some reason, but unless you are planning to scale like uber, youd be silly not to use the yt apis. Additionally, [here](https://github.com/leerob/youtube-to-mp3) is the github source for a "Youtube Audio Ripper" (MP4 to MP3) which was built using Elektron (a cross platform **javascript** framework.) So there. That is the rough design /feasibility phase completed for your project, if you choose to go this route. – Nate T Dec 21 '20 at 01:21

3 Answers3

5

I am currently using FFmpeg.wasm. It is a great tool, but I have not found a way to do this with plain JavaScript because the audio and video have different codecs sometimes. I made a function to merge videos and return a Uint8Array, which can be used in a blob.

<script src='https://unpkg.com/@ffmpeg/ffmpeg@0.9.6/dist/ffmpeg.min.js'></script>
async function mergeVideo(video, audio) {
    let { createFFmpeg, fetchFile } = FFmpeg;
    let ffmpeg = createFFmpeg();
    await ffmpeg.load();
    ffmpeg.FS('writeFile', 'video.mp4', await fetchFile(video));
    ffmpeg.FS('writeFile', 'audio.mp4', await fetchFile(audio));
    await ffmpeg.run('-i', 'video.mp4', '-i', 'audio.mp4', '-c', 'copy', 'output.mp4');
    let data = await ffmpeg.FS('readFile', 'output.mp4');
    return new Uint8Array(data.buffer);
};
myjobistobehappy
  • 736
  • 5
  • 16
4

you could give videoconverter.js a try, I have not tried it before, but I think that's the only way to do it front-end for now... and the smallest minified version also takes 6.1 MB.

Another option is upload the video to your server, merge it using ffmpeg and give user the link to output file, either to download or stream.

mido
  • 24,198
  • 15
  • 92
  • 117
  • 1
    Be aware of two things when you follow this (generally good) answer with videoconverter.js: 1) The project has been unmaintained for more than 5 years on GitHub. 2) FFmpeg is LGPL which, when used on the server, is not a problem (because hosting doesn't constitute distribution/conveying in in GPL terms), but on the frontend it might be different (because downloading JavaScript is distribution/conveying). – Clemens Kofler Dec 20 '20 at 10:17
0

Regarding the svc with the audio, consider youtube music / youtube api. It will provide all the tracks you will ever need. Just do not forget about copyright. However this is a problem you will run into wherever you go.

Nate T
  • 727
  • 5
  • 21
  • 1
    I believe that the api will let you search according to track length, but you will have to look over the details [here](https://developers.google.com/youtube/v3) – Nate T Dec 20 '20 at 23:59