Mp4mux wrong video length

I am trying saving testsrc to mp4

Why does my program record a 3-minute video when it runs for 3 seconds?

No error

async function main() {
  /* Initialize GStreamer */
  Gst.init(null);

  /* Build the pipeline */
  const pipeline = Gst.parseLaunch(`
    videotestsrc ! videoconvert ! x264enc ! h264parse ! queue ! mux.
    audiotestsrc ! audioconvert ! avenc_aac ! aacparse ! queue ! mux.
    mp4mux name=mux ! filesink location=video.mp4
  `);

  /* Start playing */
  pipeline.setState(Gst.State.PLAYING);

  /* Wait until error or EOS */
  const bus = pipeline.getBus();
  const watcher = new CustomBusWatcher(bus);

  await new Promise<Gst.Message>(async (resolve) => {
    watcher.on(Gst.MessageType.ERROR | Gst.MessageType.EOS, (msg) => {
      if (msg.type === Gst.MessageType.ERROR) {
        const [err, debugInfo] = msg.parseError();
        process.stderr.write(`Error: ${err.message}`);
        process.stderr.write(`Debug information: ${debugInfo}`);
      }
      resolve(msg);
    });

    // Wait 3 seconds and send EOS
    await new Promise((resolve) => setTimeout(resolve, 3000));
    pipeline.sendEvent(Gst.Event.newEos());
  });

  /* Free resources */
  watcher.dispose();
  bus.unref();
  pipeline.setState(Gst.State.NULL);
  pipeline.unref();
}

export class CustomBusWatcher {
  private emitter: EventEmitter;
  private intervalId: NodeJS.Timeout | null = null;

  constructor(private bus: Gst.Bus) {
    this.bus = bus;
    this.emitter = new EventEmitter();
    this.run();
  }

  run() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
    this.intervalId = setInterval(() => {
      const msg = this.bus.pop();
      if (msg) {
        for (const key of Object.values(Gst.MessageType).reverse()) {
          if (typeof key !== 'number' || key === Gst.MessageType.UNKNOWN) {
            continue;
          }
          if ((msg.type & key) === key) {
            setImmediate(() => this.emitter.emit(Gst.MessageType[key], msg));
          }
        }
      }
    }, 4);
  }

  on(event: Gst.MessageType, listener: (message: Gst.Message) => void): this {
    for (const key of Object.values(Gst.MessageType).reverse()) {
      if (typeof key !== 'number' || key === Gst.MessageType.UNKNOWN) {
        continue;
      }
      if ((event & key) === key) {
        this.emitter.on(Gst.MessageType[key], listener);
      }
    }

    return this;
  }

  dispose() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
    this.emitter.removeAllListeners();
  }
}

Your two sources are not live and will produce data as fast as possible. If you set is-live=true on both of them this should behave like you expect (but won’t be exactly 3s nonetheless).