Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

223
Views
How can I add silent audio channel/AAC codec to an MP4 file for Safari?

Wondering if anyone can help me out here!

I'm currently saving a HTML5 Canvas as an MP4 file via the MediaRecorder API. Now my canvas doesn't contain any audio but I need an audio channel built in as the file with just h.264 and no audio codec isn't compatible with a piece of software I am using.

Is there anyway to force Safari to bake in an audio codec into the stream even though there is no audio being used in the canvas?

Essentially I'm trying to achieve the following: AAC, H.264

Rather than what I have right now: H.264

Here is what I have so far (minus some other details):

  // setup media recording
  const recordedChunks = [];
  const stream = canvas.captureStream(60);

  mediaRecorder = new MediaRecorder(stream);
  mediaRecorder.ondataavailable = (e) => recordedChunks.push(e.data);
  mediaRecorder.onstop = async (e) => {
    const download = (fileName, url) => {
      const a = document.createElement("a");
      document.body.appendChild(a);
      a.style = "display: none";

      a.href = url;
      a.download = fileName;
      a.click();

      window.URL.revokeObjectURL(url);
    };

    // download video
    const videoData = new Blob(recordedChunks, { type: "video/mp4" });
    download("1.mp4", URL.createObjectURL(videoData));

  }

  // start recording
  mediaRecorder.start();

  // do some canvas related operations
  // ...

  mediaRecorder.stop();

I guess if there's no work around here I might just resort to adding a silent audio channel to the video via FFMPEG.

UPDATE: The accepted answer didn't actually work for me so I resorted to adding the audio channel through FFMPEG which worked. Accepted anyway as it does add an audio channel to the outputted file.

Thank you!

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

I'm not familiar with codecs and such but you can add a silent audio channel to a video stream as follows:

const stream = canvas.captureStream(60);

const audioContext = new AudioContext();
const oscillator = audioContext.createOscillator();
oscillator.frequency.value = 0;
const streamAudioDestination = audioContext.createMediaStreamDestination();
oscillator.connect(streamAudioDestination);
oscillator.start();

// add audio track
const audioStream = streamAudioDestination.stream;
const audioTracks = audioStream.getAudioTracks();
const firstAudioTrack = audioTracks[0];
stream.addTrack(firstAudioTrack);

const mediaRecorder = new MediaRecorder(stream);

Note that initialization of AudioContext should happen in response to a user action (e.g. within a click handler). Thank you @Nikola Lukic for noticing this!

about 4 years ago · Juan Pablo Isaza Report

0

If anybody have The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page.

Here is adapted example used @ziz Yokubjonov code:

function LOAD() {

  var canvas = document.getElementById('canvas')
  var ctx = canvas.getContext("2d")
  // setup media recording
  const recordedChunks = [];
  const stream = canvas.captureStream(60);

  // let combined = new MediaStream([...videoStream.getTracks(), ...audioStream.getTracks()]);
  let options = {
    audio: true,
    audioBitsPerSecond: 64000,
  };

  const audioContext = new AudioContext();
  const oscillator = audioContext.createOscillator();
  oscillator.frequency.value = 0;
  const streamAudioDestination = audioContext.createMediaStreamDestination();
  oscillator.connect(streamAudioDestination);
  oscillator.start();

  // add audio track
  const audioStream = streamAudioDestination.stream;
  const audioTracks = audioStream.getAudioTracks();
  const firstAudioTrack = audioTracks[0];
  stream.addTrack(firstAudioTrack);

  mediaRecorder = new MediaRecorder(stream, options);
  mediaRecorder.ondataavailable = (e) => recordedChunks.push(e.data);
  mediaRecorder.onstop = async (e) => {
    const download = (fileName, url) => {
      const a = document.createElement("a");
      document.body.appendChild(a);
      a.style = "display: block";
      a.innerHTML = 'LINK';
      a.href = url;
      a.download = fileName;
      a.click();

      window.URL.revokeObjectURL(url);
    };

    // download video
    const videoData = new Blob(recordedChunks, {type: "video/mp4"});
    download("1.mp4", URL.createObjectURL(videoData));

  }

  // start recording
  mediaRecorder.start();

  // do some canvas related operations
  var x = 10
  setInterval(function() {
    x += 20
    ctx.fillStyle = 'red'
    ctx.fillText("TEST TEST", x, 50, 200, 50);
  }, 1000)
  ctx.fillText("TEST TEST", 10, 50, 200, 50);

  setTimeout(function() {
    mediaRecorder.stop();
  }, 10000)

}

function attachFunction() {
  LOAD();
  window.removeEventListener("click", attachFunction)
}

window.addEventListener("click", attachFunction)
<canvas id='canvas'></canvas>

about 4 years ago · Juan Pablo Isaza Report

0

Thanks, maybe this will help?

    ```a.href``` = 
    url:

    ````a.download``` = 
    fileName:

    ```a.click```(.264):
    ():
    ```c.AAC```

    ```H.264```
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!