Exiv2 in the browser via WebAssembly (read/write EXIF/IPTC/XMP).
npm install exiv2-wasm
exiv2-wasm/
āā exiv2/ # submodule (Exiv2)
āā libexpat/ # submodule (expat)
āā brotli/ # submodule (google/brotli)
āā inih/ # submodule (benhoyt/inih)
āā scripts/
ā āā build.ps1 # Windows PowerShell build
ā āā build.bash # Linux/macOS bash build
āā wrapper.cpp # embind wrapper (read/write metadata)
āā index.html # demo UI page
āā dist/ # build outputs: exiv2.js / exiv2.wasm
āā (build/, deps/) # build cache / installed deps (git-ignored)
`
Clone with submodules:
`bash
git clone --recurse-submodules https://github.com/gerosyab/exiv2-wasm.git
`
---
Prerequisites
$3
- CMake, Ninja
- Emscripten SDK (emcmake / emcc / em++ / emar)
Windows (PowerShell)
`powershell
winget install Kitware.CMake
winget install Ninja-build.Ninja
`
Linux (Debian/Ubuntu)
`bash
sudo apt update
sudo apt install -y cmake ninja-build python3
`
Emscripten SDK (all OS)
`bash
anywhere you like
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
new shell(s):
source ./emsdk_env.sh # Linux/macOS
or on Windows PowerShell:
.\emsdk_env.ps1
`
> Re-run emsdk_env.sh / emsdk_env.ps1 in each new shell.
---
Build
Windows (PowerShell)
`powershell
cd exiv2-wasm
one-session policy (optional)
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
clean build
.\scripts\build.ps1 -Clean
incremental build
.\scripts\build.ps1
`
Linux/macOS (bash/zsh)
`bash
cd exiv2-wasm
chmod +x scripts/build.bash
clean build
./scripts/build.bash -c
incremental build
./scripts/build.bash
`
Outputs: dist/exiv2.js and dist/exiv2.wasm
---
Run the demo
`bash
from project root
python -m http.server 8080
open:
http://localhost:8080/index.html
`
---
JavaScript usage
Wrapper API:
- read(u8: Uint8Array) -> { exif: Object, iptc: Object, xmp: Object }
- readTagText(u8, key: string) -> string | null
- readTagBytes(u8, key: string) -> Uint8Array | null
- writeString(u8, key: string, value: string) -> Uint8Array (returns new buffer)
- writeBytes(u8, key: string, data: Uint8Array) -> Uint8Array
Browser (CDN +
Browser (CDN + ESM import)
`js
`
ESM (Node.js / Vite / webpack / Rollup)
`
import { createExiv2Module } from 'exiv2-wasm';
const exiv2 = await createExiv2Module();
const fs = await import('fs/promises');
const u8 = new Uint8Array(await fs.readFile('image.jpg'));
const meta = exiv2.read(u8);
console.log('Model:', meta.exif['Exif.Image.Model']);
`
CommonJS
`js
const { createExiv2Module } = require('exiv2-wasm');
const fs = require('fs');
function fileToU8(path) {
return new Uint8Array(fs.readFileSync(path));
}
createExiv2Module().then((exiv2) => {
const u8 = fileToU8('image.jpg');
const meta = exiv2.read(u8);
console.log('Model:', meta.exif['Exif.Image.Model']);
});
`
Common keys (examples)
- Camera: Exif.Image.Make, Exif.Image.Model
- Exposure: Exif.Photo.ExposureTime, Exif.Photo.ShutterSpeedValue
- Aperture: Exif.Photo.FNumber, Exif.Photo.ApertureValue
- ISO: Exif.Photo.PhotographicSensitivity (or Exif.Photo.ISOSpeedRatings)
- Title/Author/Comment:
- XMP: Xmp.dc.title, Xmp.dc.creator, Xmp.dc.description
- EXIF: Exif.Image.ImageDescription, Exif.Image.Artist, Exif.Photo.UserComment
- Windows XP* Unicode: Exif.Image.XPTitle, Exif.Image.XPAuthor, Exif.Image.XPComment (UTF-16LE)
---
Notes
- Exiv2 CLI build is disabled: -DEXIV2_BUILD_EXIV2_COMMAND=OFF
- BMFF/HEIF support enabled: -DEXIV2_ENABLE_BMFF=ON
- If submodules show empty after clone:
git submodule update --init --recursive`