Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

216
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda