npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

h264-mp4-encoder

v1.0.12

Published

Encode directly to H264 and ouput as an MP4 in node or on the web with WebAssembly! Works with the HTML5 Canvas :)

Downloads

22,870

Readme

Introducing h264-mp4-encoder

Encode directly to H264 and ouput as an MP4 in node or on the web with WebAssembly! Works with the HTML5 Canvas :)

See The Simple Demo or checkout the animation site it was designed for: Gifygram!

Build Status

npm install h264-mp4-encoder

Example

Web:

<script src="https://unpkg.com/h264-mp4-encoder/embuild/dist/h264-mp4-encoder.web.js"></script>

JavaScript:

const HME = require("h264-mp4-encoder");

TypeScript:

import * as HME from "h264-mp4-encoder";

Dynamic Import / Webpack:

const HME = await import("h264-mp4-encoder");
// To only import the type in TypeScript:
import("h264-mp4-encoder").H264MP4Encoder;

Example:

HME.createH264MP4Encoder().then(encoder => {
    // Must be a multiple of 2.
    encoder.width = 100;
    encoder.height = 100;
    encoder.initialize();
    // Add a single gray frame, the alpha is ignored.
    encoder.addFrameRgba(new Uint8Array(encoder.width * encoder.height * 4).fill(128))
    // For canvas:
    // encoder.addFrameRgba(ctx.getImageData(0, 0, encoder.width * encoder.height).data);
    encoder.finalize();
    const uint8Array = encoder.FS.readFile(encoder.outputFilename);
    console.log(uint8Array);
    encoder.delete();
})

You can also use await:

const encoder = await HME.createH264MP4Encoder();

Use with Webpack

When using this library with Webpack to package onto a browser environment it will report an error because it cannot resolve "fs" which is used by Emscripten's node implementation. To fix this add this to your webpack.config.js:

  "node": {
    "fs": "empty"
  },

API

/** Construct the H264MP4Encoder. Waits for the WASM to complete loading before returning. */
async function createH264MP4Encoder(): Promise<H264MP4Encoder>;

interface H264MP4Encoder {
    /**
     * Name of the file that we output.
     * After `encoder.finalize()` use `encoder.FS.readFile(encoder.outputFilename)` after `finalize`.
     * @default "output.mp4"
     */
    outputFilename: string;

    /**
     * Width of the input frames and output video. Must be a multiple of 2. Required.
     * @default 0
     */
    width: number;

    /**
     * Height of the input frames and output video. Must be a multiple of 2. Required.
     * @default 0
     */
    height: number;

    /**
     * Frame rate of the output video.
     * @default 30
     */
    frameRate: number;

    /**
     * The bitrate in kbps relative to the frame_rate. Overwrites quantization_parameter if not 0.
     * @default 0
     */
    kbps: number;

    /**
     * Speed where 0 means best quality and 10 means fastest speed [0..10].
     * @default 0
     */
    speed: number;

    /**
     * Higher means better compression, and lower means better quality [10..51].
     * @default 33
     */
    quantizationParameter: number;

    /**
     * How often a keyframe occurs (key frame period, also known as GOP).
     * @default 20
     */
    groupOfPictures: number;

    /**
     * Use temporal noise supression.
     * @default false
     */
    temporalDenoise: boolean;

    /**
     * Each NAL unit will be approximately capped at this size (0 means unlimited).
     * @default 0
     */
    desiredNaluBytes: number;

    /**
     * Prints extra debug information.
     * @default false
     */
    debug: boolean;

    /** Initialize the encoder. After calling this, all parameters above will be readonly. */
    initialize(): void;

    /** Add a frame in YUV format (expected size: width * height * 3 / 2). */
    addFrameYuv(buffer: ArrayBuffer | Uint8Array | Uint8ClampedArray | Int8Array | string): void;

    /**
     * Add a frame in RGBA format (expected size: width * height * 4).
     * Alpha is ignored but is kept for convenience of working with the HTML5 canvas.getImageData().
     */
    addFrameRgba(buffer: ArrayBuffer | Uint8Array | Uint8ClampedArray | Int8Array | string): void;

    /** Finish outputting the video to the `outputFilename`. */
    finalize(): void;

    /** Delete this object and free all resources. Should not be used again. */
    delete(): void;

    /**
     * A reference to Emscripten's virtual file system.
     * The output files will be written here under the provided `outputFilename`.
     * This file system is *shared* between all H264MP4Encoders.
     */
    FS: typeof FS;
}

How does it work?

This library brings together the public domain minih264 H264 encoder, as well as the MPL 1.1 licenced libmp4v2 to write the H264 NAL unit data into an MP4 file. Both of these are compiled in Emscripten within a Docker image and Webpacked to create easily importable modules. This repo uses submodules that are forks of those two libraries with changes for Emscripten (and to comply with the MPL 1.1 license).

Where is the WebAssembly?

To make packaging considerably easier, I built with Emscripten's -s SINGLE_FILE=1 which base64 encodes the wasm inside the JavaScript file. You're welcome to remove this option to get a wasm file, but you'll need to handle Webpack importing as well as the locateFile within the Emscripten Module object.

Building on Ubuntu

You must have docker installed, however all other depdendencies for building for node/web are within the Docker container).

./build.sh

To run the C++ code natively (not using Emscripten) you must have cmake and a compiler:

git submodule update --init --recursive
mkdir build
cd build
cmake ..
cmake --build --parallel .