{"id":30841825,"url":"https://github.com/seydx/av","last_synced_at":"2025-09-06T20:09:40.983Z","repository":{"id":311784712,"uuid":"1034415948","full_name":"seydx/av","owner":"seydx","description":"FFmpeg bindings for Node.js. Features both low-level and high-level APIs, full hardware acceleration, TypeScript support, and modern async patterns","archived":false,"fork":false,"pushed_at":"2025-09-04T15:33:33.000Z","size":8531,"stargazers_count":26,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-04T16:22:46.045Z","etag":null,"topics":["av","codec","ffmpeg","ffmpeg-wrapper","h264","h265","libav","nodejs","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seydx.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"seydx","ko_fi":"seydx","custom":"https://paypal.me/seydx"}},"created_at":"2025-08-08T11:00:12.000Z","updated_at":"2025-09-04T15:33:36.000Z","dependencies_parsed_at":"2025-08-26T20:21:36.219Z","dependency_job_id":"005e397b-ea98-4b60-a756-382a9b023d0d","html_url":"https://github.com/seydx/av","commit_stats":null,"previous_names":["seydx/av"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/seydx/av","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seydx%2Fav","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seydx%2Fav/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seydx%2Fav/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seydx%2Fav/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seydx","download_url":"https://codeload.github.com/seydx/av/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seydx%2Fav/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273956236,"owners_count":25197587,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-06T02:00:13.247Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["av","codec","ffmpeg","ffmpeg-wrapper","h264","h265","libav","nodejs","typescript"],"created_at":"2025-09-06T20:09:38.023Z","updated_at":"2025-09-06T20:09:40.974Z","avatar_url":"https://github.com/seydx.png","language":"TypeScript","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/seydx/av/blob/main/docs/logo.png?raw=true\" width=\"250px\"\u003e\n\u003c/p\u003e\n\n# NodeAV\n\n[![npm version](https://img.shields.io/npm/v/node-av.svg)](https://www.npmjs.com/package/node-av)\n[![npm downloads](https://img.shields.io/npm/dm/node-av.svg)](https://www.npmjs.com/package/node-av)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)\n[![FFmpeg](https://img.shields.io/badge/FFmpeg-7.1+-green.svg)](https://ffmpeg.org)\n[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey.svg)](https://github.com/seydx/av/tree/main/INSTALLATION.md)\n\nNative Node.js bindings for FFmpeg with full TypeScript support. Provides direct access to FFmpeg's C APIs through N-API. Includes both raw FFmpeg bindings for full control and higher-level abstractions. Automatic resource management via Disposable pattern, hardware acceleration support and prebuilt binaries for Windows, Linux, and macOS.\n\n📚 **[Documentation](https://seydx.github.io/av)**\n\n## Installation\n\n```bash\nnpm install node-av\n```\n\n## Quick Start\n\n### High-Level API\n\n```typescript\nimport { Decoder, Encoder, MediaInput, MediaOutput } from 'node-av/api';\nimport { FF_ENCODER_LIBX264 } from 'node-av/constants';\n\n// Open media\nawait using input = await MediaInput.open('input.mp4');\nawait using output = await MediaOutput.open('output.mp4');\n\n// Get video stream\nconst videoStream = input.video();\n\n// Create decoder/encoder\nusing decoder = await Decoder.create(videoStream!);\nusing encoder = await Encoder.create(FF_ENCODER_LIBX264, decoder.getOutputStreamInfo(), {\n  bitrate: '2M',\n  gopSize: 60,\n});\n\n// Add stream to output\nconst outputIndex = output.addStream(encoder);\nawait output.writeHeader();\n\n// Process packets\nfor await (const packet of input.packets()) {\n  if (packet.streamIndex === videoStream!.index) {\n    using frame = await decoder.decode(packet);\n    if (frame) {\n      using encoded = await encoder.encode(frame);\n      if (encoded) {\n        await output.writePacket(encoded, outputIndex);\n      }\n    }\n  }\n}\n\n// Flush decoder/encoder\nfor await (const frame of decoder.flushFrames()) {\n  using encoded = await encoder.encode(frame);\n  if (encoded) {\n    await output.writePacket(encoded, outputIndex);\n  }\n}\n\nfor await (const packet of encoder.flushPackets()) {\n  await output.writePacket(packet, outputIndex);\n}\n\n// End\nawait output.writeTrailer();\n```\n\n### Pipeline API\n\n```typescript\nimport { pipeline, MediaInput, MediaOutput, Decoder, Encoder } from 'node-av/api';\n\n// Simple transcode pipeline: input → decoder → encoder → output\nconst input = await MediaInput.open('input.mp4');\nconst output = await MediaOutput.open('output.mp4');\nconst decoder = await Decoder.create(input.video());\nconst encoder = await Encoder.create(FF_ENCODER_LIBX264, decoder.getOutputStreamInfo(), {\n  bitrate: '2M',\n  gopSize: 60\n});\n\nconst control = pipeline(input, decoder, encoder, output);\nawait control.completion;\n```\n\n## Hardware Acceleration\n\nThe library supports all hardware acceleration methods available in FFmpeg. The specific hardware types available depend on your FFmpeg build and system configuration.\n\n### Auto-Detection\n\n```typescript\nimport { HardwareContext } from 'node-av/api';\nimport { FF_ENCODER_H264_VIDEOTOOLBOX } from 'node-av/constants';\n\n// Automatically detect best available hardware\nconst hw = HardwareContext.auto();\nif (hw) {\n  console.log(`Using hardware: ${hw.deviceTypeName}`);\n  \n  // Use with decoder\n  const decoder = await Decoder.create(stream, {\n    hardware: hw\n  });\n  \n  // Use with encoder (use hardware-specific codec)\n  const encoder = await Encoder.create(FF_ENCODER_H264_VIDEOTOOLBOX, decoder.getOutputStreamInfo(), {\n    hardware: hw\n  });\n}\n```\n\n### Specific Hardware\n\n```typescript\nimport { AV_HWDEVICE_TYPE_CUDA, AV_HWDEVICE_TYPE_VAAPI } from 'node-av/constants';\n\n// Use specific hardware type\nconst cuda = HardwareContext.create(AV_HWDEVICE_TYPE_CUDA);\nconst vaapi = HardwareContext.create(AV_HWDEVICE_TYPE_VAAPI, '/dev/dri/renderD128');\n```\n\n## Imports and Tree Shaking\n\nThe library provides multiple entry points for optimal tree shaking:\n\n```typescript\n// High-Level API only - Recommended for most use cases\nimport { MediaInput, MediaOutput, Decoder, Encoder } from 'node-av/api';\n\n// Low-Level API only - Direct FFmpeg bindings\nimport { FormatContext, CodecContext, Frame, Packet } from 'node-av/lib';\n\n// Constants only - When you just need FFmpeg constants\nimport { AV_PIX_FMT_YUV420P, AV_CODEC_ID_H264 } from 'node-av/constants';\n\n// Channel layouts only - For audio channel configurations\nimport { AV_CHANNEL_LAYOUT_STEREO, AV_CHANNEL_LAYOUT_5POINT1 } from 'node-av/layouts';\n\n// Default export - Includes everything\nimport * as ffmpeg from 'node-av';\n```\n\n## Stream Processing\n\n### From Files\n\n```typescript\nconst media = await MediaInput.open('input.mp4');\n```\n\n### From Network\n\n```typescript\nconst media = await MediaInput.open('rtsp://example.com/stream');\n```\n\n### From Buffers\n\n```typescript\nimport { readFile } from 'fs/promises';\n\nconst buffer = await readFile('input.mp4');\nconst media = await MediaInput.open(buffer);\n```\n\n### Raw Media Processing\n\n```typescript\n// Raw video input\nconst rawVideo = await MediaInput.open({\n  type: 'video',\n  input: 'input.yuv',\n  width: 1280,\n  height: 720,\n  pixelFormat: AV_PIX_FMT_YUV420P,\n  frameRate: { num: 30, den: 1 }\n});\n\n// Raw audio input\nconst rawAudio = await MediaInput.open({\n  type: 'audio',\n  input: 'input.pcm',\n  sampleRate: 48000,\n  channels: 2,\n  sampleFormat: AV_SAMPLE_FMT_S16\n}, {\n  format: 's16le'\n});\n```\n\n## Resource Management\n\nThe library supports automatic resource cleanup using the Disposable pattern:\n\n```typescript\n// Automatic cleanup with 'using'\n{\n  await using media = await MediaInput.open('input.mp4');\n  using decoder = await Decoder.create(media.video());\n  // Resources automatically cleaned up at end of scope\n}\n\n// Manual cleanup\nconst media = await MediaInput.open('input.mp4');\ntry {\n  // Process media\n} finally {\n  await media.close();\n}\n```\n\n## Performance\n\nNodeAV executes all media operations directly through FFmpeg's native C libraries. The Node.js bindings add minimal overhead - mostly just the JavaScript-to-C boundary crossings. During typical operations like transcoding or filtering, most processing time is spent in FFmpeg's optimized C code. You get full access to hardware acceleration, SIMD optimizations, and multi-threading capabilities.\n\nHeavy and I/O operations are executed asynchronously using N-API's AsyncWorker, preventing FFmpeg calls from blocking the Node.js event loop.\n\n## Memory Safety Considerations\n\nNodeAV provides direct bindings to FFmpeg's C APIs, which work with raw memory pointers. The high-level API adds safety abstractions and automatic resource management, but incorrect usage can still cause crashes. Common issues include mismatched video dimensions, incompatible pixel formats, or improper frame buffer handling. The library validates parameters where possible, but can't guarantee complete memory safety without limiting functionality. When using the low-level API, pay attention to parameter consistency, resource cleanup, and format compatibility. Following the documented patterns helps avoid memory-related issues.\n\n## Examples\n\n| Example | FFmpeg | Low-Level API | High-Level API |\n|---------|--------|---------------|----------------|\n| `api-encode-decode` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-encode-decode.ts) |\n| `api-frame-extract` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-frame-extract.ts) |\n| `api-hw-decode-sw-encode` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-hw-decode-sw-encode.ts) |\n| `api-hw-raw` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-hw-raw.ts) |\n| `api-hw-rtsp-custom-io` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-hw-rtsp-custom-io.ts) |\n| `api-hw-rtsp` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-hw-rtsp.ts) |\n| `api-hw-transcode` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-hw-transcode.ts) |\n| `api-muxing` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-muxing.ts) |\n| `api-pipeline-hw-rtsp` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-pipeline-hw-rtsp.ts) |\n| `api-pipeline-raw-muxing` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-pipeline-raw-muxing.ts) |\n| `api-stream-input` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-stream-input.ts) |\n| `api-sw-decode-hw-encode` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-sw-decode-hw-encode.ts) |\n| `api-sw-transcode` | | | [✓](https://github.com/seydx/av/tree/main/examples/api-sw-transcode.ts) |\n| `avio-read-callback` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/avio_read_callback.c) | [✓](https://github.com/seydx/av/tree/main/examples/avio-read-callback.ts) | |\n| `decode-audio` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/decode_audio.c) | [✓](https://github.com/seydx/av/tree/main/examples/decode-audio.ts) | |\n| `decode-filter-audio` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/decode_filter_audio.c) | [✓](https://github.com/seydx/av/tree/main/examples/decode-filter-audio.ts) | |\n| `decode-filter-video` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/decode_filter_video.c) | [✓](https://github.com/seydx/av/tree/main/examples/decode-filter-video.ts) | |\n| `decode-video` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/decode_video.c) | [✓](https://github.com/seydx/av/tree/main/examples/decode-video.ts) | |\n| `demux-decode` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/demux_decode.c) | [✓](https://github.com/seydx/av/tree/main/examples/demux-decode.ts) | |\n| `encode-audio` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/encode_audio.c) | [✓](https://github.com/seydx/av/tree/main/examples/encode-audio.ts) | |\n| `encode-video` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/encode_video.c) | [✓](https://github.com/seydx/av/tree/main/examples/encode-video.ts) | |\n| `ffprobe-metadata` | | [✓](https://github.com/seydx/av/tree/main/examples/ffprobe-metadata.ts) | |\n| `filter-audio` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/filter_audio.c) | [✓](https://github.com/seydx/av/tree/main/examples/filter-audio.ts) | |\n| `hw-decode` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/hw_decode.c) | [✓](https://github.com/seydx/av/tree/main/examples/hw-decode.ts) | |\n| `hw-encode` | | [✓](https://github.com/seydx/av/tree/main/examples/hw-encode.ts) | |\n| `hw-transcode` | | [✓](https://github.com/seydx/av/tree/main/examples/hw-transcode.ts) | |\n| `qsv-decode` | [✓](https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/qsv_decode.c) | | |\n| `qsv-transcode` | [✓](https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/qsv_transcode.c) | | |\n| `vaapi-encode` | [✓](https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/vaapi_encode.c) | | |\n| `vaapi-transcode` | [✓](https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/vaapi_transcode.c) | | |\n| `mux` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/mux.c) | [✓](https://github.com/seydx/av/tree/main/examples/mux.ts) | |\n| `remux` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/remux.c) | [✓](https://github.com/seydx/av/tree/main/examples/remux.ts) | |\n| `resample-audio` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/resample_audio.c) | [✓](https://github.com/seydx/av/tree/main/examples/resample-audio.ts) | |\n| `scale-video` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/scale_video.c) | [✓](https://github.com/seydx/av/tree/main/examples/scale-video.ts) | |\n| `show-metadata` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/show_metadata.c) | [✓](https://github.com/seydx/av/tree/main/examples/show-metadata.ts) | |\n| `transcode-aac` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/transcode_aac.c) | [✓](https://github.com/seydx/av/tree/main/examples/transcode-aac.ts) | |\n| `transcode` | [✓](https://github.com/FFmpeg/FFmpeg/tree/master/doc/examples/transcode.c) | [✓](https://github.com/seydx/av/tree/main/examples/transcode.ts) | |\n\n\n## Prebuilt Binaries\n\nPrebuilt binaries are available for macOS, Linux, and Windows (x64/arm64). The package will automatically build from source if needed.\n\nFor detailed installation instructions, build requirements, and troubleshooting, see the **[Installation Guide](https://github.com/seydx/av/tree/main/INSTALLATION.md)**.\n\n## License\n\nThis project is licensed under the MIT License. See the LICENSE file for details.\n\n**Important**: FFmpeg itself is licensed under LGPL/GPL. Please ensure compliance with FFmpeg's license terms when using this library. The FFmpeg libraries themselves retain their original licenses, and this wrapper library does not change those terms. See [FFmpeg License](https://ffmpeg.org/legal.html) for details.\n\n## Contributing\n\nContributions are welcome! Please read [CONTRIBUTING.md](https://github.com/seydx/av/tree/main/CONTRIBUTING.md) for development setup, code standards, and contribution guidelines before submitting pull requests.\n\n## Support\n\nFor issues and questions, please use the GitHub issue tracker.\n\n## See Also\n\n- [FFmpeg Documentation](https://ffmpeg.org/documentation.html)\n- [FFmpeg Doxygen](https://ffmpeg.org/doxygen/trunk/)\n- [Jellyfin FFmpeg](https://github.com/jellyfin/jellyfin-ffmpeg)\n","funding_links":["https://github.com/sponsors/seydx","https://ko-fi.com/seydx","https://paypal.me/seydx"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseydx%2Fav","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseydx%2Fav","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseydx%2Fav/lists"}