first
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
# Skills
|
||||
|
||||
A skill provides reference documentation for a specific tool or service. Skills are used by tasks to accomplish their goals. Each skill lives in its own directory under `skills/` and is defined by a `SKILL.md` file.
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
skills/
|
||||
<skill-name>/
|
||||
SKILL.md
|
||||
```
|
||||
|
||||
## SKILL.md Format
|
||||
|
||||
A skill file has two parts: **frontmatter** (YAML metadata) and **body** (Markdown documentation).
|
||||
|
||||
### Frontmatter
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: skill-name
|
||||
description: What this skill does and when to use it.
|
||||
---
|
||||
```
|
||||
|
||||
#### Fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `name` | string | yes | Identifier for the skill. |
|
||||
| `description` | string | yes | What the skill does and when to use it. Should include trigger phrases (e.g., "Use when the user wants to..."). |
|
||||
|
||||
### Body
|
||||
|
||||
The body contains reference documentation for the tool or service. The structure varies depending on the type of skill, but typically includes:
|
||||
|
||||
- **Title** — `# Skill Name`
|
||||
- **Overview** — What the tool is and how it works.
|
||||
- **Usage** — How to invoke the tool (endpoints, CLI synopsis, etc.).
|
||||
- **Parameters/Options** — Detailed reference tables.
|
||||
- **Examples** — Common usage patterns and recipes.
|
||||
- **Source** — Links to official documentation and repositories.
|
||||
|
||||
### Existing Skills
|
||||
|
||||
| Skill | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `whisper.cpp` | HTTP API | Speech-to-text transcription via a local whisper.cpp server. |
|
||||
| `ffmpeg` | CLI | Audio/video processing, conversion, and analysis. |
|
||||
@@ -0,0 +1,474 @@
|
||||
---
|
||||
name: ffmpeg
|
||||
description: Process audio and video files using ffmpeg/ffprobe. Use when the user wants to convert, transcode, trim, merge, extract, resize, compress, or analyze multimedia files.
|
||||
---
|
||||
|
||||
# FFmpeg
|
||||
|
||||
CLI reference for FFmpeg v8.x — a complete, cross-platform solution for recording, converting, and streaming audio and video.
|
||||
|
||||
Official docs: https://www.ffmpeg.org/documentation.html
|
||||
|
||||
## Tools
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| `ffmpeg` | Transcode, convert, filter, mux/demux multimedia |
|
||||
| `ffprobe` | Analyze and inspect multimedia streams |
|
||||
| `ffplay` | Play multimedia files (interactive) |
|
||||
|
||||
---
|
||||
|
||||
## ffmpeg
|
||||
|
||||
### Synopsis
|
||||
|
||||
```
|
||||
ffmpeg [global_options] {[input_options] -i input_url} ... {[output_options] output_url} ...
|
||||
```
|
||||
|
||||
Options before `-i` apply to the input; options before the output URL apply to the output.
|
||||
|
||||
### Global Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-y` | Overwrite output files without asking |
|
||||
| `-n` | Do not overwrite; exit if output exists |
|
||||
| `-hide_banner` | Suppress copyright/build info banner |
|
||||
| `-loglevel level` | Set log level: `quiet`, `error`, `warning`, `info` (default), `verbose`, `debug` |
|
||||
| `-stats` | Print encoding progress/statistics |
|
||||
| `-progress url` | Send machine-readable progress to url |
|
||||
| `-report` | Dump full command line and log to a file |
|
||||
| `-filter_threads n` | Number of threads for filter processing |
|
||||
|
||||
### Input/Output Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-i url` | Input file URL |
|
||||
| `-f fmt` | Force input or output format |
|
||||
| `-c[:stream] codec` | Select encoder/decoder; use `copy` for stream copying |
|
||||
| `-t duration` | Limit duration (as input: read limit; as output: write limit) |
|
||||
| `-to position` | Stop at position (timestamp) |
|
||||
| `-ss position` | Seek to position (before `-i`: fast input seek; after: output seek) |
|
||||
| `-sseof position` | Seek relative to end of file |
|
||||
| `-itsoffset offset` | Set input time offset |
|
||||
| `-itsscale scale` | Rescale input timestamps |
|
||||
| `-metadata key=value` | Set metadata key/value pair |
|
||||
| `-disposition value` | Set stream disposition flags |
|
||||
| `-target type` | Specify target type: `vcd`, `svcd`, `dvd`, `dv`, `dv50` |
|
||||
| `-stream_loop n` | Loop input stream n times (-1 = infinite) |
|
||||
| `-frames[:stream] n` | Stop after n frames |
|
||||
| `-fs limit` | Set file size limit in bytes |
|
||||
| `-timestamp date` | Set recording timestamp |
|
||||
|
||||
### Video Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-vn` | Disable video |
|
||||
| `-vcodec codec` | Set video codec (alias for `-c:v`) |
|
||||
| `-r fps` | Set frame rate |
|
||||
| `-fpsmax fps` | Set maximum frame rate |
|
||||
| `-s WxH` | Set frame size |
|
||||
| `-aspect ratio` | Set display aspect ratio (e.g. `16:9`) |
|
||||
| `-pix_fmt format` | Set pixel format |
|
||||
| `-vf filtergraph` | Apply video filter graph (alias for `-filter:v`) |
|
||||
| `-pass n` | Two-pass encoding pass (1 or 2) |
|
||||
| `-passlogfile prefix` | Two-pass log file prefix |
|
||||
| `-vframes n` | Set number of video frames to output |
|
||||
| `-autorotate` | Auto-rotate based on metadata (default on) |
|
||||
| `-display_rotation angle` | Set video rotation metadata |
|
||||
| `-display_hflip` | Horizontal flip metadata |
|
||||
| `-display_vflip` | Vertical flip metadata |
|
||||
| `-force_key_frames expr` | Force keyframes at specified times/expression |
|
||||
| `-copyinkf` | Copy non-key frames at the beginning during stream copy |
|
||||
|
||||
### Audio Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-an` | Disable audio |
|
||||
| `-acodec codec` | Set audio codec (alias for `-c:a`) |
|
||||
| `-ar freq` | Set audio sample rate (Hz) |
|
||||
| `-ac channels` | Set number of audio channels |
|
||||
| `-af filtergraph` | Apply audio filter graph (alias for `-filter:a`) |
|
||||
| `-sample_fmt fmt` | Set audio sample format |
|
||||
| `-channel_layout layout` | Set audio channel layout |
|
||||
| `-aq q` | Set audio quality (codec-specific VBR) |
|
||||
| `-aframes n` | Set number of audio frames to output |
|
||||
|
||||
### Subtitle Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-sn` | Disable subtitles |
|
||||
| `-scodec codec` | Set subtitle codec (alias for `-c:s`) |
|
||||
| `-fix_sub_duration` | Fix subtitle durations to avoid overlap |
|
||||
|
||||
### Stream Selection
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-map input:stream` | Manually select streams for output |
|
||||
| `-dn` | Disable data streams |
|
||||
|
||||
Stream specifiers: `v` (video), `V` (video, no images), `a` (audio), `s` (subtitle), `d` (data). Index with `:N` (e.g. `a:0` = first audio).
|
||||
|
||||
### Hardware Acceleration
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-hwaccel method` | HW accel method: `cuda`, `vaapi`, `qsv`, `vulkan`, `auto` |
|
||||
| `-hwaccel_device device` | Select HW device |
|
||||
| `-init_hw_device type=name` | Initialize HW device |
|
||||
|
||||
---
|
||||
|
||||
## ffprobe
|
||||
|
||||
### Synopsis
|
||||
|
||||
```
|
||||
ffprobe [options] input_url
|
||||
```
|
||||
|
||||
### Main Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-show_format` | Show container format info |
|
||||
| `-show_streams` | Show per-stream info |
|
||||
| `-show_packets` | Show per-packet info |
|
||||
| `-show_frames` | Show per-frame info |
|
||||
| `-show_chapters` | Show chapter info |
|
||||
| `-show_programs` | Show program info |
|
||||
| `-show_entries section=key1,key2` | Show only specific fields |
|
||||
| `-show_error` | Show probe errors |
|
||||
| `-select_streams specifier` | Filter to specific streams (e.g. `v:0`, `a`) |
|
||||
| `-count_frames` | Count frames per stream |
|
||||
| `-count_packets` | Count packets per stream |
|
||||
| `-read_intervals intervals` | Analyze specific time ranges |
|
||||
|
||||
### Output Formats
|
||||
|
||||
Set with `-output_format` (or `-of`, `-print_format`):
|
||||
|
||||
| Format | Description |
|
||||
|--------|-------------|
|
||||
| `default` | `[SECTION] key=value [/SECTION]` |
|
||||
| `json` | JSON output (most useful for parsing) |
|
||||
| `xml` | XML output |
|
||||
| `csv` | Comma-separated values |
|
||||
| `flat` | Flat `key=value` per line |
|
||||
| `ini` | INI-style sections |
|
||||
|
||||
### Display Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-pretty` | Human-readable units and time formatting |
|
||||
| `-unit` | Show value units |
|
||||
| `-sexagesimal` | Format times as HH:MM:SS.us |
|
||||
| `-hide_banner` | Suppress copyright/build info |
|
||||
| `-o output_url` | Write output to file instead of stdout |
|
||||
|
||||
---
|
||||
|
||||
## Common Codecs
|
||||
|
||||
### Video Encoders
|
||||
|
||||
#### libx264 (H.264)
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-preset` | Speed/quality: `ultrafast`, `superfast`, `veryfast`, `faster`, `fast`, `medium` (default), `slow`, `slower`, `veryslow` |
|
||||
| `-crf` | Constant quality: 0 (lossless) to 51 (worst). 18-23 is typical |
|
||||
| `-profile:v` | `baseline`, `main`, `high` |
|
||||
| `-tune` | `film`, `animation`, `grain`, `stillimage`, `fastdecode`, `zerolatency` |
|
||||
| `-b:v` | Target bitrate (e.g. `2M`) |
|
||||
|
||||
#### libx265 (H.265/HEVC)
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-preset` | Same presets as x264 |
|
||||
| `-crf` | 0-51, default 28. Similar quality to x264 at lower bitrate |
|
||||
| `-profile:v` | `main`, `main10`, `main12` |
|
||||
| `-b:v` | Target bitrate |
|
||||
|
||||
#### libvpx-vp9 (VP9)
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-crf` | 0-63. 31 is a good default |
|
||||
| `-b:v` | Target bitrate (set to `0` for pure CRF mode) |
|
||||
| `-cpu-used` | Speed: 0 (slowest/best) to 8 (fastest) |
|
||||
| `-deadline` | `best`, `good` (default), `realtime` |
|
||||
| `-row-mt 1` | Enable row-based multithreading |
|
||||
|
||||
#### libsvtav1 (SVT-AV1)
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-crf` | 0-63. 30 is a good default |
|
||||
| `-preset` | 0 (slowest/best) to 13 (fastest). 8 is a good default |
|
||||
| `-b:v` | Target bitrate |
|
||||
|
||||
#### libaom-av1 (AOM AV1)
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-crf` | 0-63 |
|
||||
| `-cpu-used` | 0 (best) to 8 (fastest) |
|
||||
| `-b:v` | Target bitrate (set to `0` for pure CRF mode) |
|
||||
| `-tiles` | Tile columns x rows for parallelism |
|
||||
|
||||
### Audio Encoders
|
||||
|
||||
#### aac (Native AAC)
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-b:a` | Bitrate: `128k`, `192k`, `256k` |
|
||||
| `-profile:a` | `aac_low` (default), `aac_he`, `aac_he_v2` |
|
||||
|
||||
#### libmp3lame (MP3)
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-b:a` | CBR bitrate: `128k`, `192k`, `320k` |
|
||||
| `-q:a` | VBR quality: 0 (best) to 9 (worst). 2 is a good default |
|
||||
|
||||
#### libopus (Opus)
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-b:a` | Bitrate: `64k` to `256k`. 128k is a good default |
|
||||
| `-vbr` | `on` (default), `off`, `constrained` |
|
||||
| `-application` | `audio` (default), `voip`, `lowdelay` |
|
||||
|
||||
#### libvorbis (Vorbis)
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-q:a` | VBR quality: -1 to 10. 5 is a good default |
|
||||
| `-b:a` | ABR bitrate |
|
||||
|
||||
#### flac (FLAC)
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `-compression_level` | 0 (fast) to 12 (best). 5 is default |
|
||||
|
||||
---
|
||||
|
||||
## Common Container Formats
|
||||
|
||||
| Format | Extensions | Notes |
|
||||
|--------|-----------|-------|
|
||||
| `mp4` | .mp4, .m4a, .m4v | Use `-movflags +faststart` for web streaming |
|
||||
| `matroska` | .mkv | Supports virtually all codecs |
|
||||
| `webm` | .webm | VP8/VP9/AV1 + Vorbis/Opus for web |
|
||||
| `avi` | .avi | Legacy; limited codec support |
|
||||
| `mpegts` | .ts | Broadcast transport stream |
|
||||
| `ogg` | .ogg, .ogv | Vorbis/Opus/Theora container |
|
||||
| `wav` | .wav | Uncompressed PCM audio |
|
||||
| `flac` | .flac | Lossless audio |
|
||||
| `mp3` | .mp3 | MPEG audio layer 3 |
|
||||
| `hls` | .m3u8 | HTTP Live Streaming |
|
||||
| `dash` | .mpd | DASH adaptive streaming |
|
||||
| `gif` | .gif | Animated GIF |
|
||||
| `image2` | various | Image sequence input/output |
|
||||
| `concat` | text file | Concatenation demuxer (file list) |
|
||||
| `null` | — | Discard output (benchmarking) |
|
||||
|
||||
---
|
||||
|
||||
## Common Video Filters (`-vf`)
|
||||
|
||||
| Filter | Description | Example |
|
||||
|--------|-------------|---------|
|
||||
| `scale=W:H` | Resize video. Use `-1` or `-2` to auto-calculate | `scale=1280:720`, `scale=-2:480` |
|
||||
| `crop=W:H:X:Y` | Crop to WxH starting at X,Y | `crop=640:480:100:50` |
|
||||
| `pad=W:H:X:Y:color` | Pad video with borders | `pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black` |
|
||||
| `overlay=X:Y` | Composite second input over first | `overlay=10:10` |
|
||||
| `transpose=N` | Rotate: 0=90ccw+vflip, 1=90cw, 2=90ccw, 3=90cw+vflip | `transpose=1` |
|
||||
| `hflip` / `vflip` | Horizontal / vertical flip | `hflip` |
|
||||
| `rotate=angle` | Rotate by arbitrary angle (radians) | `rotate=PI/4` |
|
||||
| `fps=N` | Change frame rate | `fps=30` |
|
||||
| `setpts=expr` | Modify presentation timestamps | `setpts=0.5*PTS` (2x speed) |
|
||||
| `trim=start:end` | Extract time range | `trim=start=10:end=20` |
|
||||
| `drawtext=opts` | Overlay text | `drawtext=text='Hello':fontsize=24:x=10:y=10` |
|
||||
| `fade=t=type:st=S:d=D` | Fade in/out | `fade=t=in:st=0:d=2` |
|
||||
| `eq=opts` | Adjust brightness/contrast/saturation | `eq=brightness=0.1:contrast=1.2` |
|
||||
| `format=pix_fmt` | Convert pixel format | `format=yuv420p` |
|
||||
| `concat=n:v:a` | Concatenate segments | `concat=n=2:v=1:a=1` |
|
||||
| `split` / `select` | Duplicate / select frames | `select='eq(pict_type,I)'` |
|
||||
| `deinterlace` / `yadif` | Remove interlacing | `yadif=1` |
|
||||
| `boxblur=R` | Apply box blur | `boxblur=5:1` |
|
||||
| `subtitles=file` | Burn in subtitles from file | `subtitles=subs.srt` |
|
||||
| `palettegen` / `paletteuse` | Generate/apply palette for GIF | Used in two-pass GIF creation |
|
||||
| `colorchannelmixer` | Mix color channels | `colorchannelmixer=.3:.4:.3:0:.3:.4:.3:0:.3:.4:.3` (grayscale) |
|
||||
|
||||
## Common Audio Filters (`-af`)
|
||||
|
||||
| Filter | Description | Example |
|
||||
|--------|-------------|---------|
|
||||
| `volume=V` | Adjust volume | `volume=1.5`, `volume=-3dB` |
|
||||
| `loudnorm` | EBU R128 loudness normalization | `loudnorm=I=-16:TP=-1.5:LRA=11` |
|
||||
| `atempo=T` | Change tempo (0.5-100.0) | `atempo=2.0` (2x speed) |
|
||||
| `aresample=rate` | Resample audio | `aresample=44100` |
|
||||
| `amerge` | Merge audio channels | `amerge=inputs=2` |
|
||||
| `afade=t=type:st=S:d=D` | Audio fade in/out | `afade=t=in:st=0:d=3` |
|
||||
| `highpass=f=freq` | High-pass filter | `highpass=f=200` |
|
||||
| `lowpass=f=freq` | Low-pass filter | `lowpass=f=3000` |
|
||||
| `equalizer=f:t:w:g` | Parametric EQ | `equalizer=f=1000:t=q:w=1:g=5` |
|
||||
| `acompressor` | Dynamic range compression | `acompressor=threshold=-20dB:ratio=4` |
|
||||
| `silenceremove` | Remove silence | `silenceremove=1:0:-50dB` |
|
||||
| `silencedetect` | Detect silence | `silencedetect=n=-30dB:d=2` |
|
||||
| `adelay=delays` | Delay audio channels | `adelay=1000\|1000` (ms) |
|
||||
| `aecho=id:ig:delays:decays` | Add echo effect | `aecho=0.8:0.88:60:0.4` |
|
||||
| `pan=layout:gains` | Remix channels | `pan=mono\|c0=0.5*c0+0.5*c1` |
|
||||
|
||||
---
|
||||
|
||||
## Common Recipes
|
||||
|
||||
### Convert format
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mkv output.mp4
|
||||
```
|
||||
|
||||
### Transcode with CRF quality
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 -c:v libx264 -crf 20 -c:a aac -b:a 192k output.mp4
|
||||
```
|
||||
|
||||
### Extract audio
|
||||
|
||||
```bash
|
||||
ffmpeg -i video.mp4 -vn -c:a copy audio.m4a
|
||||
```
|
||||
|
||||
### Extract video (no audio)
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 -an -c:v copy output.mp4
|
||||
```
|
||||
|
||||
### Trim / cut
|
||||
|
||||
```bash
|
||||
ffmpeg -ss 00:01:30 -to 00:03:00 -i input.mp4 -c copy output.mp4
|
||||
```
|
||||
|
||||
### Resize video
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 -vf "scale=1280:720" -c:a copy output.mp4
|
||||
```
|
||||
|
||||
### Compress video (lower quality)
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 128k output.mp4
|
||||
```
|
||||
|
||||
### Two-pass encoding
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -pass 1 -f null /dev/null
|
||||
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -pass 2 output.mp4
|
||||
```
|
||||
|
||||
### Concatenate files (concat demuxer)
|
||||
|
||||
```bash
|
||||
# files.txt contains:
|
||||
# file 'part1.mp4'
|
||||
# file 'part2.mp4'
|
||||
ffmpeg -f concat -safe 0 -i files.txt -c copy output.mp4
|
||||
```
|
||||
|
||||
### Add subtitles (burn-in)
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 -vf "subtitles=subs.srt" output.mp4
|
||||
```
|
||||
|
||||
### Create GIF
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" output.gif
|
||||
```
|
||||
|
||||
### Add watermark / overlay
|
||||
|
||||
```bash
|
||||
ffmpeg -i video.mp4 -i logo.png -filter_complex "overlay=10:10" output.mp4
|
||||
```
|
||||
|
||||
### Change speed (video + audio)
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" -af "atempo=2.0" output.mp4
|
||||
```
|
||||
|
||||
### Extract frames as images
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 -vf "fps=1" frame_%04d.png
|
||||
```
|
||||
|
||||
### Merge audio and video
|
||||
|
||||
```bash
|
||||
ffmpeg -i video.mp4 -i audio.m4a -c:v copy -c:a copy -shortest output.mp4
|
||||
```
|
||||
|
||||
### Normalize audio loudness
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 -af "loudnorm=I=-16:TP=-1.5:LRA=11" -c:v copy output.mp4
|
||||
```
|
||||
|
||||
### Convert to web-optimized MP4
|
||||
|
||||
```bash
|
||||
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k -movflags +faststart output.mp4
|
||||
```
|
||||
|
||||
### Probe file info (JSON)
|
||||
|
||||
```bash
|
||||
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
|
||||
```
|
||||
|
||||
### Get duration only
|
||||
|
||||
```bash
|
||||
ffprobe -v quiet -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4
|
||||
```
|
||||
|
||||
### Get resolution only
|
||||
|
||||
```bash
|
||||
ffprobe -v quiet -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 input.mp4
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Source
|
||||
|
||||
- Website: https://ffmpeg.org/
|
||||
- Documentation: https://www.ffmpeg.org/documentation.html
|
||||
- CLI reference: https://www.ffmpeg.org/ffmpeg.html
|
||||
- Filters reference: https://www.ffmpeg.org/ffmpeg-filters.html
|
||||
- Codecs reference: https://www.ffmpeg.org/ffmpeg-codecs.html
|
||||
- Formats reference: https://www.ffmpeg.org/ffmpeg-formats.html
|
||||
- Wiki: https://trac.ffmpeg.org/wiki
|
||||
@@ -0,0 +1,168 @@
|
||||
---
|
||||
name: fizzy-cli
|
||||
description: Manage Fizzy boards, cards, columns, and comments from the command line. Use when the user wants to create, list, update, or organize cards and boards on Fizzy.
|
||||
---
|
||||
|
||||
# Fizzy CLI
|
||||
|
||||
CLI reference for fizzy-cli — a command-line interface for the Fizzy API to manage boards, cards, columns, comments, and more.
|
||||
|
||||
Source: https://github.com/robzolkos/fizzy-cli
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration sources in order of precedence (highest first):
|
||||
|
||||
1. **Command-line flags** (`--token`, `--account`, `--api-url`)
|
||||
2. **Environment variables** (`FIZZY_TOKEN`, `FIZZY_ACCOUNT`, `FIZZY_API_URL`, `FIZZY_BOARD`)
|
||||
3. **Local project config** (`.fizzy.yaml` in current or parent directories)
|
||||
4. **Global config** (`~/.config/fizzy/config.yaml` or `~/.fizzy/config.yaml`)
|
||||
|
||||
Run `fizzy setup` for interactive configuration.
|
||||
|
||||
## Global Options
|
||||
|
||||
| Flag | Env Variable | Description |
|
||||
|------|-------------|-------------|
|
||||
| `--token` | `FIZZY_TOKEN` | API access token |
|
||||
| `--account` | `FIZZY_ACCOUNT` | Account identifier |
|
||||
| `--api-url` | `FIZZY_API_URL` | API base URL (default: `https://app.fizzy.do`) |
|
||||
| `--verbose` | — | Display request/response details |
|
||||
|
||||
---
|
||||
|
||||
## Commands
|
||||
|
||||
### Boards
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `fizzy board list` | List all boards |
|
||||
| `fizzy board show BOARD_ID` | Display board details |
|
||||
| `fizzy board create --name "Name"` | Create a new board |
|
||||
| `fizzy board update BOARD_ID --name "Name"` | Update a board |
|
||||
| `fizzy board delete BOARD_ID` | Delete a board |
|
||||
|
||||
### Cards
|
||||
|
||||
#### List cards
|
||||
|
||||
```bash
|
||||
fizzy card list [--board ID] [--column ID] [--tag ID] [--assignee ID]
|
||||
fizzy card list [--sort newest|oldest|latest] [--search "text"]
|
||||
fizzy card list [--created thisweek] [--closed thisweek] [--unassigned]
|
||||
```
|
||||
|
||||
#### CRUD
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `fizzy card show CARD_ID` | View card details |
|
||||
| `fizzy card create --board ID --title "Title"` | Create a card |
|
||||
| `fizzy card update CARD_ID --title "Title"` | Update a card |
|
||||
| `fizzy card delete CARD_ID` | Delete a card |
|
||||
|
||||
#### Card actions
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `fizzy card close CARD_ID` | Close a card |
|
||||
| `fizzy card reopen CARD_ID` | Reopen a card |
|
||||
| `fizzy card move CARD_ID --to BOARD_ID` | Move card to another board |
|
||||
| `fizzy card postpone CARD_ID` | Postpone a card |
|
||||
| `fizzy card column CARD_ID --column COLUMN_ID` | Assign card to a column |
|
||||
| `fizzy card assign CARD_ID --user USER_ID` | Assign card to a user |
|
||||
| `fizzy card tag CARD_ID --tag "tag"` | Tag a card |
|
||||
| `fizzy card pin CARD_ID` | Pin a card |
|
||||
| `fizzy card unpin CARD_ID` | Unpin a card |
|
||||
| `fizzy card golden CARD_ID` | Mark card as golden |
|
||||
| `fizzy card ungolden CARD_ID` | Remove golden status |
|
||||
| `fizzy card watch CARD_ID` | Watch a card |
|
||||
| `fizzy card unwatch CARD_ID` | Unwatch a card |
|
||||
|
||||
#### Card attachments
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `fizzy card attachments show CARD_ID` | List attachments |
|
||||
| `fizzy card attachments download CARD_ID` | Download all attachments |
|
||||
| `fizzy card attachments download CARD_ID ATT_ID` | Download specific attachment |
|
||||
|
||||
### Columns
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `fizzy column list --board ID` | List columns |
|
||||
| `fizzy column show COLUMN_ID --board ID` | View column |
|
||||
| `fizzy column create --board ID --name "Name"` | Create column |
|
||||
| `fizzy column update COLUMN_ID --board ID --name "Name"` | Update column |
|
||||
| `fizzy column delete COLUMN_ID --board ID` | Delete column |
|
||||
|
||||
### Comments
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `fizzy comment list --card CARD_ID` | List comments |
|
||||
| `fizzy comment show COMMENT_ID --card CARD_ID` | View comment |
|
||||
| `fizzy comment create --card CARD_ID --body "Text"` | Add comment |
|
||||
| `fizzy comment update COMMENT_ID --card CARD_ID --body "Text"` | Edit comment |
|
||||
| `fizzy comment delete COMMENT_ID --card CARD_ID` | Delete comment |
|
||||
|
||||
#### Comment attachments
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `fizzy comment attachments show --card CARD_ID` | List attachments |
|
||||
| `fizzy comment attachments download --card CARD_ID` | Download all |
|
||||
| `fizzy comment attachments download --card CARD_ID ATT_ID` | Download specific |
|
||||
|
||||
### Steps (To-Do Items)
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `fizzy step show STEP_ID --card CARD_ID` | View step |
|
||||
| `fizzy step create --card CARD_ID --content "Task"` | Create step |
|
||||
| `fizzy step update STEP_ID --card CARD_ID --completed` | Mark step complete |
|
||||
| `fizzy step delete STEP_ID --card CARD_ID` | Delete step |
|
||||
|
||||
### Reactions
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `fizzy reaction list --card CARD_ID` | List reactions |
|
||||
| `fizzy reaction create --card CARD_ID --content "👍"` | Add reaction |
|
||||
| `fizzy reaction delete REACTION_ID --card CARD_ID` | Remove reaction |
|
||||
|
||||
### Users & Tags
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `fizzy user list` | List users |
|
||||
| `fizzy user show USER_ID` | View user details |
|
||||
| `fizzy tag list` | List available tags |
|
||||
|
||||
### Pins, Search & Notifications
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `fizzy pin list` | List pinned cards |
|
||||
| `fizzy search "term"` | Full-text card search |
|
||||
| `fizzy notification list` | List notifications |
|
||||
| `fizzy notification read ID` | Mark notification as read |
|
||||
| `fizzy notification unread ID` | Mark notification as unread |
|
||||
| `fizzy notification read-all` | Mark all notifications as read |
|
||||
|
||||
### File Uploads
|
||||
|
||||
```bash
|
||||
fizzy upload file /path/to/file.png
|
||||
# Returns: { "signed_id": "...", "attachable_sgid": "..." }
|
||||
```
|
||||
|
||||
Use `signed_id` for card headers; `attachable_sgid` for inline images in rich text.
|
||||
|
||||
---
|
||||
|
||||
## Source
|
||||
|
||||
- Repository: https://github.com/robzolkos/fizzy-cli
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"id":"44cc6c97-2a5e-4c39-86a7-121e4ecf2bab"}
|
||||
@@ -0,0 +1,343 @@
|
||||
---
|
||||
name: mlx.audio
|
||||
description: Generate speech from text and transcribe audio using mlx-audio. Use when the user wants text-to-speech synthesis, speech-to-text transcription, voice cloning, audio separation, or speech-to-speech processing on Apple Silicon.
|
||||
---
|
||||
|
||||
# MLX-Audio
|
||||
|
||||
A speech processing library built on Apple's MLX framework, providing TTS, STT, speech-to-speech (STS), and audio separation optimized for Apple Silicon.
|
||||
|
||||
- **Repository:** https://github.com/Blaizzy/mlx-audio
|
||||
- **License:** MIT
|
||||
|
||||
## CLI Tools
|
||||
|
||||
### Text-to-Speech (TTS)
|
||||
|
||||
```bash
|
||||
mlx_audio.tts.generate --model <model> --text '<text>' [options]
|
||||
```
|
||||
|
||||
| Flag | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `--model` | string | required | HuggingFace model ID |
|
||||
| `--text` | string | required | Text to synthesize |
|
||||
| `--voice` | string | — | Voice preset (model-specific) |
|
||||
| `--speed` | float | 1.0 | Speech speed multiplier |
|
||||
| `--lang_code` | string | `a` | Language code |
|
||||
| `--play` | flag | — | Play audio immediately |
|
||||
| `--output_path` | string | — | Directory to save audio |
|
||||
| `--ref_audio` | string | — | Reference audio for voice cloning (CSM) |
|
||||
|
||||
#### Language Codes
|
||||
|
||||
| Code | Language |
|
||||
|------|----------|
|
||||
| `a` | American English |
|
||||
| `b` | British English |
|
||||
| `j` | Japanese |
|
||||
| `z` | Mandarin Chinese |
|
||||
| `e` | Spanish |
|
||||
| `f` | French |
|
||||
|
||||
#### Kokoro Voices
|
||||
|
||||
| Voice | Description |
|
||||
|-------|-------------|
|
||||
| `af_heart`, `af_bella`, `af_nova`, `af_sky` | American female |
|
||||
| `am_adam`, `am_echo` | American male |
|
||||
| `bf_alice`, `bf_emma` | British female |
|
||||
| `bm_daniel`, `bm_george` | British male |
|
||||
| `jf_alpha`, `jm_kumo` | Japanese |
|
||||
| `zf_xiaobei`, `zm_yunxi` | Chinese |
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Basic generation
|
||||
mlx_audio.tts.generate --model mlx-community/Kokoro-82M-bf16 --text 'Hello, world!' --lang_code a
|
||||
|
||||
# With voice and speed
|
||||
mlx_audio.tts.generate --model mlx-community/Kokoro-82M-bf16 --text 'Hello!' --voice af_heart --speed 1.2 --lang_code a
|
||||
|
||||
# Play immediately
|
||||
mlx_audio.tts.generate --model mlx-community/Kokoro-82M-bf16 --text 'Hello!' --play --lang_code a
|
||||
|
||||
# Voice cloning with CSM
|
||||
mlx_audio.tts.generate --model mlx-community/csm-1b --text "Hello from Sesame." --ref_audio ./reference_voice.wav --play
|
||||
```
|
||||
|
||||
### Speech-to-Text (STT)
|
||||
|
||||
```bash
|
||||
python -m mlx_audio.stt.generate --model <model> --audio <file> [options]
|
||||
```
|
||||
|
||||
| Flag | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `--model` | string | required | HuggingFace model ID |
|
||||
| `--audio` | string | required | Input audio file |
|
||||
| `--language` | string | — | Language code |
|
||||
| `--max-tokens` | int | 1024 | Maximum output tokens |
|
||||
| `--temperature` | float | 0.0 | Sampling temperature |
|
||||
| `--context` | string | — | Hotwords/metadata for context |
|
||||
| `--output-path` | string | — | Output directory |
|
||||
| `--format` | string | — | Output format (e.g. `json`) |
|
||||
| `--stream` | flag | — | Enable streaming mode |
|
||||
| `--verbose` | flag | — | Detailed logging |
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Basic transcription
|
||||
python -m mlx_audio.stt.generate --model mlx-community/whisper-large-v3-turbo-asr-fp16 --audio speech.wav --verbose
|
||||
|
||||
# With context for technical terms
|
||||
python -m mlx_audio.stt.generate --model mlx-community/VibeVoice-ASR-bf16 --audio meeting.wav --context "MLX, Apple Silicon, PyTorch" --max-tokens 8192 --format json --verbose
|
||||
|
||||
# Parakeet model
|
||||
python -m mlx_audio.stt.generate --model mlx-community/parakeet-tdt-0.6b-v3 --audio speech.wav --format json --verbose
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Python API
|
||||
|
||||
### TTS
|
||||
|
||||
```python
|
||||
from mlx_audio.tts.utils import load_model
|
||||
|
||||
model = load_model("mlx-community/Kokoro-82M-bf16")
|
||||
for result in model.generate("Hello from MLX-Audio!", voice="af_heart"):
|
||||
audio = result.audio # mx.array waveform
|
||||
```
|
||||
|
||||
### STT
|
||||
|
||||
```python
|
||||
from mlx_audio.stt.generate import generate_transcription
|
||||
|
||||
result = generate_transcription(
|
||||
model="mlx-community/whisper-large-v3-turbo-asr-fp16",
|
||||
audio="audio.wav",
|
||||
)
|
||||
print(result.text)
|
||||
```
|
||||
|
||||
### STT with Streaming
|
||||
|
||||
```python
|
||||
from mlx_audio.stt import load
|
||||
|
||||
# VibeVoice-ASR streaming
|
||||
model = load("mlx-community/VibeVoice-ASR-bf16")
|
||||
for text in model.stream_transcribe(audio="speech.wav", max_tokens=4096):
|
||||
print(text, end="", flush=True)
|
||||
|
||||
# Parakeet streaming
|
||||
model = load("mlx-community/parakeet-tdt-0.6b-v3")
|
||||
for chunk in model.generate("long_audio.wav", stream=True):
|
||||
print(chunk.text, end="", flush=True)
|
||||
```
|
||||
|
||||
### Forced Alignment (Qwen3)
|
||||
|
||||
```python
|
||||
from mlx_audio.stt import load
|
||||
|
||||
aligner = load("mlx-community/Qwen3-ForcedAligner-0.6B-8bit")
|
||||
result = aligner.generate("audio.wav", text="I have a dream", language="English")
|
||||
for item in result:
|
||||
print(f"[{item.start_time:.2f}s - {item.end_time:.2f}s] {item.text}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## REST API Server (OpenAI-compatible)
|
||||
|
||||
### Starting the Server
|
||||
|
||||
```bash
|
||||
python -m mlx_audio.server [OPTIONS]
|
||||
```
|
||||
|
||||
| Flag | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `--host` | string | `localhost` | Server host |
|
||||
| `--port` | int | `8000` | Server port |
|
||||
| `--allowed-origins` | string | `*` | CORS allowed origins |
|
||||
| `--workers` | int/float | `2` | Number of workers |
|
||||
| `--reload` | flag | — | Enable auto-reload |
|
||||
| `--start-ui` | flag | — | Launch Studio UI alongside API |
|
||||
| `--log-dir` | string | `logs` | Directory for server logs |
|
||||
|
||||
### Endpoints
|
||||
|
||||
#### GET /v1/models
|
||||
|
||||
List available models.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/v1/models
|
||||
```
|
||||
|
||||
#### POST /v1/models?model_name=\<name\>
|
||||
|
||||
Add a model to the server.
|
||||
|
||||
#### DELETE /v1/models?model_name=\<name\>
|
||||
|
||||
Remove a model from the server.
|
||||
|
||||
#### POST /v1/audio/speech
|
||||
|
||||
Generate speech from text.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/v1/audio/speech \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "mlx-community/Kokoro-82M-bf16",
|
||||
"input": "Hello, world!",
|
||||
"voice": "af_heart",
|
||||
"speed": 1.0,
|
||||
"lang_code": "a",
|
||||
"response_format": "mp3"
|
||||
}' --output speech.mp3
|
||||
```
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `model` | string | required | Model ID |
|
||||
| `input` | string | required | Text to synthesize |
|
||||
| `voice` | string | — | Voice preset |
|
||||
| `speed` | float | 1.0 | Speech speed |
|
||||
| `lang_code` | string | `a` | Language code |
|
||||
| `ref_audio` | string | — | Reference audio path (voice cloning) |
|
||||
| `ref_text` | string | — | Reference transcript |
|
||||
| `response_format` | string | `mp3` | Output format |
|
||||
| `stream` | bool | false | Enable streaming |
|
||||
| `streaming_interval` | float | 2.0 | Streaming chunk interval |
|
||||
| `temperature` | float | 0.7 | Sampling temperature |
|
||||
| `top_p` | float | 0.95 | Nucleus sampling |
|
||||
| `top_k` | int | 40 | Top-k sampling |
|
||||
| `repetition_penalty` | float | 1.0 | Repetition penalty |
|
||||
| `max_tokens` | int | 1200 | Maximum tokens |
|
||||
| `gender` | string | `male` | Gender hint |
|
||||
| `pitch` | float | 1.0 | Pitch adjustment |
|
||||
| `instruct` | string | — | Instruction text |
|
||||
|
||||
#### POST /v1/audio/transcriptions
|
||||
|
||||
Transcribe an audio file (multipart/form-data).
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/v1/audio/transcriptions \
|
||||
-F file=@audio.wav \
|
||||
-F model=mlx-community/whisper-large-v3-turbo-asr-fp16
|
||||
```
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `file` | file | required | Audio file |
|
||||
| `model` | string | required | Model ID |
|
||||
| `language` | string | — | Language code |
|
||||
| `max_tokens` | int | 1024 | Maximum tokens |
|
||||
| `chunk_duration` | float | 30.0 | Chunk duration (seconds) |
|
||||
| `stream` | bool | false | Enable streaming |
|
||||
| `context` | string | — | Hotwords/context |
|
||||
| `text` | string | — | Reference text |
|
||||
| `verbose` | bool | false | Detailed output |
|
||||
|
||||
Response (NDJSON stream):
|
||||
|
||||
```json
|
||||
{"text": "chunk text", "accumulated": "full text so far"}
|
||||
```
|
||||
|
||||
#### WebSocket /v1/audio/transcriptions/realtime
|
||||
|
||||
Real-time transcription via WebSocket. Send initial config as JSON, then stream int16 PCM audio as binary frames.
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "mlx-community/whisper-large-v3-turbo-asr-fp16",
|
||||
"sample_rate": 16000,
|
||||
"streaming": true
|
||||
}
|
||||
```
|
||||
|
||||
#### POST /v1/audio/separations
|
||||
|
||||
Separate audio sources (multipart/form-data).
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/v1/audio/separations \
|
||||
-F file=@audio.wav \
|
||||
-F model=mlx-community/sam-audio-large-fp16 \
|
||||
-F description="speech"
|
||||
```
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `file` | file | required | Audio file |
|
||||
| `model` | string | `mlx-community/sam-audio-large-fp16` | Model ID |
|
||||
| `description` | string | `speech` | Target description |
|
||||
| `method` | string | `midpoint` | ODE method (`midpoint` or `euler`) |
|
||||
| `steps` | int | 16 | ODE steps (2/4/8/16/32) |
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"target": "<base64 WAV>",
|
||||
"residual": "<base64 WAV>",
|
||||
"sample_rate": 44100
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Supported Models
|
||||
|
||||
### TTS Models
|
||||
|
||||
| Model | Languages | Notes |
|
||||
|-------|-----------|-------|
|
||||
| Kokoro | EN, JA, ZH, FR, ES, IT, PT, HI | Fast, high-quality multilingual |
|
||||
| Qwen3-TTS | ZH, EN, JA, KO, + more | Voice design via instruction |
|
||||
| CSM | EN | Voice cloning with reference audio |
|
||||
| Dia | EN | Dialogue-focused |
|
||||
| OuteTTS | EN | Efficient |
|
||||
| Spark | EN, ZH | SparkTTS |
|
||||
| Chatterbox | EN, ES, FR, DE, IT, PT, PL, TR, RU, NL, CS, AR, ZH, JA, HU, KO | Expressive multilingual |
|
||||
| Soprano | EN | High-quality |
|
||||
|
||||
### STT Models
|
||||
|
||||
| Model | Languages | Notes |
|
||||
|-------|-----------|-------|
|
||||
| Whisper | 99+ languages | OpenAI's robust model |
|
||||
| Qwen3-ASR | ZH, EN, JA, KO, + more | Alibaba multilingual |
|
||||
| Qwen3-ForcedAligner | ZH, EN, JA, KO, + more | Word-level alignment |
|
||||
| Parakeet | EN (v2), 25 EU languages (v3) | NVIDIA, high accuracy |
|
||||
| Voxtral | Multiple | Mistral speech model |
|
||||
| Voxtral Realtime | Multiple | 4B streaming STT |
|
||||
| VibeVoice-ASR | Multiple | Microsoft 9B, supports diarization and context |
|
||||
|
||||
### Other Models
|
||||
|
||||
| Model | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| Sortformer v1/v2.1 | VAD/Diarization | Speaker diarization (up to 4 speakers) |
|
||||
| SAM-Audio | Separation | Text-guided source separation |
|
||||
| Liquid2.5-Audio | STS | Speech/text-to-speech and STT |
|
||||
| MossFormer2 SE | Enhancement | Speech enhancement / noise removal |
|
||||
|
||||
Models are available from `mlx-community` on HuggingFace with various quantization levels (3-bit through 8-bit and fp16/bf16).
|
||||
|
||||
## Source
|
||||
|
||||
- Repository: https://github.com/Blaizzy/mlx-audio
|
||||
- HuggingFace: https://huggingface.co/mlx-community
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"id":"6abfee78-52e6-4d64-9641-5ad92f2995c3"}
|
||||
@@ -0,0 +1,533 @@
|
||||
---
|
||||
name: mutagen
|
||||
description: Read and write audio metadata using the mutagen Python library. Use when the user wants to read, edit, embed, or remove tags (title, artist, album, cover art, lyrics, etc.) in MP3, FLAC, MP4/M4A, OGG, and other audio files.
|
||||
---
|
||||
|
||||
# Mutagen
|
||||
|
||||
API reference for mutagen — a Python library for reading and writing audio metadata (tags) across multiple formats.
|
||||
|
||||
No dependencies outside the Python standard library. Supports Python 3.10+ (CPython and PyPy).
|
||||
|
||||
Official docs: https://mutagen.readthedocs.io
|
||||
Repository: https://github.com/quodlibet/mutagen
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install mutagen
|
||||
```
|
||||
|
||||
## Supported Formats
|
||||
|
||||
| Format | Class | Tag System |
|
||||
|--------|-------|------------|
|
||||
| MP3 | `mutagen.mp3.MP3` / `EasyMP3` | ID3v2 |
|
||||
| FLAC | `mutagen.flac.FLAC` | Vorbis Comments |
|
||||
| MP4 / M4A | `mutagen.mp4.MP4` / `EasyMP4` | iTunes-style atoms |
|
||||
| Ogg Vorbis | `mutagen.oggvorbis.OggVorbis` | Vorbis Comments |
|
||||
| Ogg Opus | `mutagen.oggopus.OggOpus` | Vorbis Comments |
|
||||
| Ogg FLAC | `mutagen.oggflac.OggFLAC` | Vorbis Comments |
|
||||
| Ogg Speex | `mutagen.oggspeex.OggSpeex` | Vorbis Comments |
|
||||
| Ogg Theora | `mutagen.oggtheora.OggTheora` | Vorbis Comments |
|
||||
| ASF / WMA | `mutagen.asf.ASF` | ASF attributes |
|
||||
| AIFF | `mutagen.aiff.AIFF` | ID3v2 |
|
||||
| WavPack | `mutagen.wavpack.WavPack` | APEv2 |
|
||||
| Musepack | `mutagen.musepack.Musepack` | APEv2 |
|
||||
| Monkey's Audio | `mutagen.monkeysaudio.MonkeysAudio` | APEv2 |
|
||||
| True Audio | `mutagen.trueaudio.TrueAudio` | ID3v2 / APEv2 |
|
||||
| OptimFROG | `mutagen.optimfrog.OptimFROG` | APEv2 |
|
||||
|
||||
## Core API
|
||||
|
||||
### Auto-Detection with `mutagen.File()`
|
||||
|
||||
```python
|
||||
import mutagen
|
||||
|
||||
audio = mutagen.File("song.mp3") # auto-detects format
|
||||
print(audio.info.length) # duration in seconds
|
||||
print(audio.tags) # tag object (format-specific)
|
||||
```
|
||||
|
||||
`mutagen.File()` returns the appropriate `FileType` subclass, or `None` if unrecognized.
|
||||
|
||||
Pass `easy=True` to get simplified tag access (EasyID3/EasyMP4):
|
||||
|
||||
```python
|
||||
audio = mutagen.File("song.mp3", easy=True)
|
||||
audio["title"] = ["My Song"]
|
||||
audio.save()
|
||||
```
|
||||
|
||||
### FileType (Base Class)
|
||||
|
||||
All format classes inherit from `FileType` and share this interface:
|
||||
|
||||
| Attribute / Method | Description |
|
||||
|--------------------|-------------|
|
||||
| `.info` | `StreamInfo` object — `length`, `bitrate`, `sample_rate`, `channels` |
|
||||
| `.tags` | Tag object (dict-like), or `None` if no tags |
|
||||
| `.mime` | List of applicable MIME types |
|
||||
| `.save()` | Write tags to file |
|
||||
| `.delete()` | Remove all tags from file |
|
||||
| `.add_tags()` | Create new empty tag object (raises error if tags exist) |
|
||||
| `.pprint()` | Human-readable stream info and tags |
|
||||
|
||||
---
|
||||
|
||||
## ID3 Tags (MP3, AIFF, TrueAudio)
|
||||
|
||||
### Reading / Writing with Raw ID3
|
||||
|
||||
```python
|
||||
from mutagen.mp3 import MP3
|
||||
from mutagen.id3 import ID3, TIT2, TPE1, TALB, TRCK, TDRC, TCON, APIC, COMM, USLT
|
||||
|
||||
audio = MP3("song.mp3")
|
||||
|
||||
# Read
|
||||
print(audio["TIT2"].text[0]) # title
|
||||
print(audio["TPE1"].text[0]) # artist
|
||||
|
||||
# Write
|
||||
audio["TIT2"] = TIT2(encoding=3, text=["My Title"])
|
||||
audio["TPE1"] = TPE1(encoding=3, text=["My Artist"])
|
||||
audio.save()
|
||||
```
|
||||
|
||||
### Common ID3 Frames
|
||||
|
||||
| Frame | Class | Description | Constructor |
|
||||
|-------|-------|-------------|-------------|
|
||||
| `TIT2` | TextFrame | Title | `TIT2(encoding=3, text=["..."])` |
|
||||
| `TPE1` | TextFrame | Artist / Performer | `TPE1(encoding=3, text=["..."])` |
|
||||
| `TPE2` | TextFrame | Album Artist | `TPE2(encoding=3, text=["..."])` |
|
||||
| `TALB` | TextFrame | Album | `TALB(encoding=3, text=["..."])` |
|
||||
| `TRCK` | NumericPartTextFrame | Track number (`"N/Total"`) | `TRCK(encoding=3, text=["1/12"])` |
|
||||
| `TPOS` | NumericPartTextFrame | Disc number (`"N/Total"`) | `TPOS(encoding=3, text=["1/2"])` |
|
||||
| `TDRC` | TimeStampTextFrame | Recording date | `TDRC(encoding=3, text=["2024"])` |
|
||||
| `TCON` | TextFrame | Genre | `TCON(encoding=3, text=["Rock"])` |
|
||||
| `TCOM` | TextFrame | Composer | `TCOM(encoding=3, text=["..."])` |
|
||||
| `TBPM` | NumericTextFrame | BPM | `TBPM(encoding=3, text=["120"])` |
|
||||
| `COMM` | TextFrame | Comment | `COMM(encoding=3, lang="eng", desc="", text=["..."])` |
|
||||
| `USLT` | TextFrame | Lyrics | `USLT(encoding=3, lang="eng", desc="", text="...")` |
|
||||
| `APIC` | Frame | Attached picture | `APIC(encoding=3, mime="image/jpeg", type=3, desc="", data=bytes)` |
|
||||
|
||||
### Encoding Values
|
||||
|
||||
| Value | Encoding |
|
||||
|-------|----------|
|
||||
| `0` | Latin-1 |
|
||||
| `1` | UTF-16 |
|
||||
| `2` | UTF-16BE |
|
||||
| `3` | UTF-8 (recommended) |
|
||||
|
||||
### APIC Picture Types
|
||||
|
||||
| Value | Meaning |
|
||||
|-------|---------|
|
||||
| `0` | Other |
|
||||
| `3` | Cover (front) |
|
||||
| `4` | Cover (back) |
|
||||
| `6` | Media (e.g. label side of CD) |
|
||||
|
||||
### ID3 Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `.add(frame)` | Add a frame (replaces matching frame) |
|
||||
| `.getall(key)` | Get all frames matching key prefix |
|
||||
| `.delall(key)` | Delete all frames matching key prefix |
|
||||
| `.update_to_v23()` | Convert tags to ID3v2.3 (call before saving as v2.3) |
|
||||
| `.update_to_v24()` | Convert tags to ID3v2.4 |
|
||||
| `.save(v2_version=4)` | Save; set `v2_version=3` for ID3v2.3 |
|
||||
|
||||
### EasyID3 (Simplified Interface)
|
||||
|
||||
```python
|
||||
from mutagen.easyid3 import EasyID3
|
||||
|
||||
audio = EasyID3("song.mp3")
|
||||
audio["title"] = ["My Title"]
|
||||
audio["artist"] = ["My Artist"]
|
||||
audio["album"] = ["My Album"]
|
||||
audio["tracknumber"] = ["1/12"]
|
||||
audio["date"] = ["2024"]
|
||||
audio["genre"] = ["Rock"]
|
||||
audio.save()
|
||||
```
|
||||
|
||||
Available EasyID3 keys: `title`, `artist`, `albumartist`, `album`, `tracknumber`, `discnumber`, `date`, `genre`, `composer`, `bpm`, `length`, `organization`, `website`, and more.
|
||||
|
||||
---
|
||||
|
||||
## MP3 Stream Info
|
||||
|
||||
```python
|
||||
from mutagen.mp3 import MP3
|
||||
|
||||
audio = MP3("song.mp3")
|
||||
info = audio.info
|
||||
```
|
||||
|
||||
| Attribute | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `info.length` | float | Duration in seconds |
|
||||
| `info.bitrate` | int | Bits per second |
|
||||
| `info.sample_rate` | int | Sampling frequency (Hz) |
|
||||
| `info.channels` | int | Number of channels |
|
||||
| `info.bitrate_mode` | BitrateMode | `UNKNOWN`, `CBR`, `VBR`, `ABR` |
|
||||
| `info.encoder_info` | str | Encoder name/version |
|
||||
| `info.track_gain` | float\|None | ReplayGain track gain |
|
||||
| `info.track_peak` | float\|None | ReplayGain track peak |
|
||||
| `info.album_gain` | float\|None | ReplayGain album gain |
|
||||
|
||||
---
|
||||
|
||||
## FLAC
|
||||
|
||||
```python
|
||||
from mutagen.flac import FLAC
|
||||
|
||||
audio = FLAC("song.flac")
|
||||
```
|
||||
|
||||
FLAC uses Vorbis Comments — tags are simple string key-value pairs (case-insensitive keys, multiple values per key).
|
||||
|
||||
### Reading / Writing Tags
|
||||
|
||||
```python
|
||||
audio["title"] = ["My Title"]
|
||||
audio["artist"] = ["My Artist"]
|
||||
audio["album"] = ["My Album"]
|
||||
audio["tracknumber"] = ["1"]
|
||||
audio["date"] = ["2024"]
|
||||
audio.save()
|
||||
```
|
||||
|
||||
### Stream Info
|
||||
|
||||
| Attribute | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `info.length` | float | Duration in seconds |
|
||||
| `info.bitrate` | int | Bits per second |
|
||||
| `info.sample_rate` | int | Sampling frequency (Hz) |
|
||||
| `info.channels` | int | Number of channels |
|
||||
| `info.bits_per_sample` | int | Bit depth |
|
||||
| `info.total_samples` | int | Total number of samples |
|
||||
|
||||
### Embedded Pictures
|
||||
|
||||
```python
|
||||
from mutagen.flac import FLAC, Picture
|
||||
|
||||
audio = FLAC("song.flac")
|
||||
|
||||
# Add picture
|
||||
pic = Picture()
|
||||
with open("cover.jpg", "rb") as f:
|
||||
pic.data = f.read()
|
||||
pic.type = 3 # front cover
|
||||
pic.mime = "image/jpeg"
|
||||
pic.width = 500
|
||||
pic.height = 500
|
||||
pic.depth = 24
|
||||
audio.add_picture(pic)
|
||||
audio.save()
|
||||
|
||||
# Read pictures
|
||||
for pic in audio.pictures:
|
||||
print(pic.mime, pic.type, len(pic.data))
|
||||
|
||||
# Remove all pictures
|
||||
audio.clear_pictures()
|
||||
audio.save()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MP4 / M4A
|
||||
|
||||
```python
|
||||
from mutagen.mp4 import MP4
|
||||
|
||||
audio = MP4("song.m4a")
|
||||
```
|
||||
|
||||
### Common Tag Keys
|
||||
|
||||
| Key | Description |
|
||||
|-----|-------------|
|
||||
| `"\xa9nam"` | Title |
|
||||
| `"\xa9ART"` | Artist |
|
||||
| `"\xa9alb"` | Album |
|
||||
| `"aART"` | Album artist |
|
||||
| `"\xa9wrt"` | Composer |
|
||||
| `"\xa9gen"` | Genre |
|
||||
| `"\xa9day"` | Year / Date |
|
||||
| `"\xa9lyr"` | Lyrics |
|
||||
| `"\xa9cmt"` | Comment |
|
||||
| `"trkn"` | Track number — `[(track, total)]` |
|
||||
| `"disk"` | Disc number — `[(disc, total)]` |
|
||||
| `"tmpo"` | BPM — `[120]` |
|
||||
| `"cpil"` | Compilation — `True`/`False` |
|
||||
| `"pgap"` | Gapless playback — `True`/`False` |
|
||||
| `"covr"` | Cover art — list of `MP4Cover` objects |
|
||||
|
||||
### Reading / Writing Tags
|
||||
|
||||
```python
|
||||
audio["\xa9nam"] = ["My Title"]
|
||||
audio["\xa9ART"] = ["My Artist"]
|
||||
audio["trkn"] = [(1, 12)]
|
||||
audio.save()
|
||||
```
|
||||
|
||||
### Cover Art
|
||||
|
||||
```python
|
||||
from mutagen.mp4 import MP4, MP4Cover
|
||||
|
||||
audio = MP4("song.m4a")
|
||||
|
||||
# Add cover
|
||||
with open("cover.jpg", "rb") as f:
|
||||
cover = MP4Cover(f.read(), imageformat=MP4Cover.FORMAT_JPEG)
|
||||
audio["covr"] = [cover]
|
||||
audio.save()
|
||||
|
||||
# Read cover
|
||||
for cover in audio["covr"]:
|
||||
print(cover.imageformat) # FORMAT_JPEG or FORMAT_PNG
|
||||
# cover is bytes-like — write directly to file
|
||||
```
|
||||
|
||||
### MP4 Cover Formats
|
||||
|
||||
| Constant | Value |
|
||||
|----------|-------|
|
||||
| `MP4Cover.FORMAT_JPEG` | JPEG |
|
||||
| `MP4Cover.FORMAT_PNG` | PNG |
|
||||
|
||||
### Stream Info
|
||||
|
||||
| Attribute | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `info.length` | float | Duration in seconds |
|
||||
| `info.bitrate` | int | Bits per second |
|
||||
| `info.sample_rate` | int | Sampling frequency (Hz) |
|
||||
| `info.channels` | int | Number of channels |
|
||||
| `info.bits_per_sample` | int | Bit depth |
|
||||
| `info.codec` | str | Codec identifier (e.g. `"mp4a.40.2"`, `"alac"`) |
|
||||
| `info.codec_description` | str | Human-readable codec name |
|
||||
|
||||
### EasyMP4
|
||||
|
||||
```python
|
||||
from mutagen.easymp4 import EasyMP4
|
||||
|
||||
audio = EasyMP4("song.m4a")
|
||||
audio["title"] = ["My Title"]
|
||||
audio["artist"] = ["My Artist"]
|
||||
audio.save()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Ogg Vorbis
|
||||
|
||||
```python
|
||||
from mutagen.oggvorbis import OggVorbis
|
||||
|
||||
audio = OggVorbis("song.ogg")
|
||||
```
|
||||
|
||||
Uses Vorbis Comments — same string key-value interface as FLAC:
|
||||
|
||||
```python
|
||||
audio["title"] = ["My Title"]
|
||||
audio["artist"] = ["My Artist"]
|
||||
audio.save()
|
||||
```
|
||||
|
||||
### Stream Info
|
||||
|
||||
| Attribute | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `info.length` | float | Duration in seconds |
|
||||
| `info.bitrate` | int | Nominal bitrate (bits/s) |
|
||||
| `info.sample_rate` | int | Sampling frequency (Hz) |
|
||||
| `info.channels` | int | Number of channels |
|
||||
|
||||
---
|
||||
|
||||
## Ogg Opus
|
||||
|
||||
```python
|
||||
from mutagen.oggopus import OggOpus
|
||||
|
||||
audio = OggOpus("song.opus")
|
||||
audio["title"] = ["My Title"]
|
||||
audio.save()
|
||||
```
|
||||
|
||||
Same Vorbis Comments interface. Stream info includes `info.length`, `info.channels`.
|
||||
|
||||
---
|
||||
|
||||
## Common Recipes
|
||||
|
||||
### Read all tags (any format)
|
||||
|
||||
```python
|
||||
import mutagen
|
||||
|
||||
audio = mutagen.File("song.mp3")
|
||||
for key, value in audio.tags.items():
|
||||
print(f"{key}: {value}")
|
||||
```
|
||||
|
||||
### Set title and artist (any format, easy mode)
|
||||
|
||||
```python
|
||||
import mutagen
|
||||
|
||||
audio = mutagen.File("song.mp3", easy=True)
|
||||
audio["title"] = ["My Title"]
|
||||
audio["artist"] = ["My Artist"]
|
||||
audio.save()
|
||||
```
|
||||
|
||||
### Embed cover art in MP3
|
||||
|
||||
```python
|
||||
from mutagen.mp3 import MP3
|
||||
from mutagen.id3 import ID3, APIC
|
||||
|
||||
audio = MP3("song.mp3")
|
||||
if audio.tags is None:
|
||||
audio.add_tags()
|
||||
|
||||
with open("cover.jpg", "rb") as f:
|
||||
audio.tags.add(APIC(
|
||||
encoding=3,
|
||||
mime="image/jpeg",
|
||||
type=3, # front cover
|
||||
desc="Cover",
|
||||
data=f.read()
|
||||
))
|
||||
audio.save()
|
||||
```
|
||||
|
||||
### Extract cover art from MP3
|
||||
|
||||
```python
|
||||
from mutagen.mp3 import MP3
|
||||
|
||||
audio = MP3("song.mp3")
|
||||
for tag in audio.tags.getall("APIC"):
|
||||
with open("extracted_cover.jpg", "wb") as f:
|
||||
f.write(tag.data)
|
||||
```
|
||||
|
||||
### Embed cover art in FLAC
|
||||
|
||||
```python
|
||||
from mutagen.flac import FLAC, Picture
|
||||
|
||||
audio = FLAC("song.flac")
|
||||
pic = Picture()
|
||||
with open("cover.jpg", "rb") as f:
|
||||
pic.data = f.read()
|
||||
pic.type = 3
|
||||
pic.mime = "image/jpeg"
|
||||
pic.width = 500
|
||||
pic.height = 500
|
||||
pic.depth = 24
|
||||
audio.add_picture(pic)
|
||||
audio.save()
|
||||
```
|
||||
|
||||
### Embed cover art in MP4/M4A
|
||||
|
||||
```python
|
||||
from mutagen.mp4 import MP4, MP4Cover
|
||||
|
||||
audio = MP4("song.m4a")
|
||||
with open("cover.jpg", "rb") as f:
|
||||
audio["covr"] = [MP4Cover(f.read(), imageformat=MP4Cover.FORMAT_JPEG)]
|
||||
audio.save()
|
||||
```
|
||||
|
||||
### Add lyrics to MP3
|
||||
|
||||
```python
|
||||
from mutagen.mp3 import MP3
|
||||
from mutagen.id3 import USLT
|
||||
|
||||
audio = MP3("song.mp3")
|
||||
audio.tags.add(USLT(encoding=3, lang="eng", desc="", text="Lyrics here..."))
|
||||
audio.save()
|
||||
```
|
||||
|
||||
### Remove all tags
|
||||
|
||||
```python
|
||||
import mutagen
|
||||
|
||||
audio = mutagen.File("song.mp3")
|
||||
audio.delete()
|
||||
audio.save()
|
||||
```
|
||||
|
||||
### Copy tags between files
|
||||
|
||||
```python
|
||||
from mutagen.easyid3 import EasyID3
|
||||
|
||||
src = EasyID3("source.mp3")
|
||||
dst = EasyID3("dest.mp3")
|
||||
for key in src:
|
||||
dst[key] = src[key]
|
||||
dst.save()
|
||||
```
|
||||
|
||||
### Batch-read metadata from directory
|
||||
|
||||
```python
|
||||
import mutagen
|
||||
from pathlib import Path
|
||||
|
||||
for path in Path(".").glob("*.mp3"):
|
||||
audio = mutagen.File(str(path), easy=True)
|
||||
if audio and audio.tags:
|
||||
title = audio.tags.get("title", ["Unknown"])[0]
|
||||
artist = audio.tags.get("artist", ["Unknown"])[0]
|
||||
print(f"{path.name}: {artist} - {title}")
|
||||
```
|
||||
|
||||
### Save as ID3v2.3 (compatibility)
|
||||
|
||||
```python
|
||||
from mutagen.mp3 import MP3
|
||||
|
||||
audio = MP3("song.mp3")
|
||||
audio.tags.update_to_v23()
|
||||
audio.save(v2_version=3)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Source
|
||||
|
||||
- Repository: https://github.com/quodlibet/mutagen
|
||||
- Documentation: https://mutagen.readthedocs.io/en/latest/
|
||||
- PyPI: https://pypi.org/project/mutagen/
|
||||
- API — Base: https://mutagen.readthedocs.io/en/latest/api/base.html
|
||||
- API — ID3: https://mutagen.readthedocs.io/en/latest/api/id3.html
|
||||
- API — ID3 Frames: https://mutagen.readthedocs.io/en/latest/api/id3_frames.html
|
||||
- API — MP3: https://mutagen.readthedocs.io/en/latest/api/mp3.html
|
||||
- API — MP4: https://mutagen.readthedocs.io/en/latest/api/mp4.html
|
||||
- API — FLAC: https://mutagen.readthedocs.io/en/latest/api/flac.html
|
||||
- API — Ogg Vorbis: https://mutagen.readthedocs.io/en/latest/api/oggvorbis.html
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"id":"da96d8ac-cb9d-4d46-81b6-d2cfde733863"}
|
||||
@@ -0,0 +1,725 @@
|
||||
---
|
||||
name: sharp
|
||||
description: Process images using the sharp Node.js library. Use when the user wants to resize, convert, crop, composite, transform, or optimize images programmatically.
|
||||
---
|
||||
|
||||
# Sharp
|
||||
|
||||
API reference for sharp — a high-performance Node.js image processing library built on libvips.
|
||||
|
||||
Typically 4-5x faster than ImageMagick/GraphicsMagick. Supports JPEG, PNG, WebP, GIF, AVIF, TIFF, SVG, HEIF, JP2, and JXL.
|
||||
|
||||
Official docs: https://sharp.pixelplumbing.com
|
||||
Repository: https://github.com/lovell/sharp
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install sharp
|
||||
```
|
||||
|
||||
Requires Node.js ^18.17.0 or >= 20.3.0 (or Deno/Bun with Node-API v9).
|
||||
|
||||
## Usage
|
||||
|
||||
Sharp uses a fluent, chainable API. Every call returns a Sharp instance.
|
||||
|
||||
```js
|
||||
import sharp from 'sharp';
|
||||
|
||||
await sharp('input.jpg')
|
||||
.resize(800, 600)
|
||||
.jpeg({ quality: 80 })
|
||||
.toFile('output.jpg');
|
||||
```
|
||||
|
||||
Sharp implements `stream.Duplex` — it can be piped to/from.
|
||||
|
||||
---
|
||||
|
||||
## Constructor
|
||||
|
||||
```js
|
||||
sharp([input], [options])
|
||||
```
|
||||
|
||||
- `input` (Buffer | string | Array): Image buffer, file path, array of inputs, or omit for stream input.
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `failOn` | string | `'warning'` | `'none'`, `'truncated'`, `'error'`, `'warning'` |
|
||||
| `limitInputPixels` | number \| boolean | `268402689` | Max pixels; `false` to disable |
|
||||
| `unlimited` | boolean | `false` | Remove memory safety for JPEG/PNG/SVG/HEIF |
|
||||
| `autoOrient` | boolean | `false` | Auto-rotate per EXIF Orientation |
|
||||
| `sequentialRead` | boolean | `true` | Sequential vs random access |
|
||||
| `density` | number | `72` | DPI for vector images (1-100000) |
|
||||
| `ignoreIcc` | boolean | `false` | Ignore embedded ICC profile |
|
||||
| `pages` | number | `1` | Pages to extract; `-1` for all |
|
||||
| `page` | number | `0` | Starting page (zero-based) |
|
||||
| `animated` | boolean | `false` | Read all frames (equiv. `pages: -1`) |
|
||||
|
||||
### Raw Input
|
||||
|
||||
```js
|
||||
sharp(buffer, { raw: { width: 100, height: 100, channels: 4 } })
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `width` | number | Pixel width |
|
||||
| `height` | number | Pixel height |
|
||||
| `channels` | number | 1-4 |
|
||||
| `premultiplied` | boolean | Skip premultiplication (default `false`) |
|
||||
|
||||
### Create New Image
|
||||
|
||||
```js
|
||||
sharp({ create: { width: 300, height: 200, channels: 4, background: '#ff0000' } })
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `width` | number | Pixel width |
|
||||
| `height` | number | Pixel height |
|
||||
| `channels` | number | 3 (RGB) or 4 (RGBA) |
|
||||
| `background` | string \| Object | Color (parsed by color module) |
|
||||
| `noise` | Object | `{ type: 'gaussian', mean: 128, sigma: 30 }` |
|
||||
|
||||
### Render Text
|
||||
|
||||
```js
|
||||
sharp({ text: { text: 'Hello', font: 'Arial', dpi: 150 } })
|
||||
```
|
||||
|
||||
| Property | Type | Default | Description |
|
||||
|----------|------|---------|-------------|
|
||||
| `text` | string | -- | UTF-8; supports Pango markup |
|
||||
| `font` | string | -- | Font name |
|
||||
| `fontfile` | string | -- | Absolute path to font file |
|
||||
| `width` | number | `0` | Word-wrap boundary; 0 = no wrap |
|
||||
| `height` | number | `0` | Max height |
|
||||
| `align` | string | `'left'` | `'left'`, `'centre'`, `'center'`, `'right'` |
|
||||
| `justify` | boolean | `false` | Text justification |
|
||||
| `dpi` | number | `72` | Render resolution |
|
||||
| `rgba` | boolean | `false` | RGBA for color emoji/Pango markup |
|
||||
| `spacing` | number | `0` | Line height in points |
|
||||
| `wrap` | string | `'word'` | `'word'`, `'char'`, `'word-char'`, `'none'` |
|
||||
|
||||
### Join Array
|
||||
|
||||
```js
|
||||
sharp([img1, img2, img3], { join: { across: 3, shim: 10 } })
|
||||
```
|
||||
|
||||
| Property | Type | Default | Description |
|
||||
|----------|------|---------|-------------|
|
||||
| `across` | number | `1` | Images per row |
|
||||
| `animated` | boolean | `false` | Join as animated image |
|
||||
| `shim` | number | `0` | Pixel gap between images |
|
||||
| `background` | string \| Object | -- | Gap fill color |
|
||||
| `halign` | string | `'left'` | `'left'`, `'centre'`, `'right'` |
|
||||
| `valign` | string | `'top'` | `'top'`, `'centre'`, `'bottom'` |
|
||||
|
||||
### Clone
|
||||
|
||||
```js
|
||||
const pipeline = sharp('input.jpg');
|
||||
const clone1 = pipeline.clone().resize(200).toFile('thumb.jpg');
|
||||
const clone2 = pipeline.clone().resize(800).toFile('large.jpg');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Resize
|
||||
|
||||
```js
|
||||
.resize([width], [height], [options])
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `width` | number | -- | Target width (null to auto-scale) |
|
||||
| `height` | number | -- | Target height (null to auto-scale) |
|
||||
| `fit` | string | `'cover'` | `'cover'`, `'contain'`, `'fill'`, `'inside'`, `'outside'` |
|
||||
| `position` | string | `'centre'` | Gravity/position for cover/contain |
|
||||
| `background` | string \| Object | `{r:0,g:0,b:0,alpha:1}` | Fill color for `contain` |
|
||||
| `kernel` | string | `'lanczos3'` | `'nearest'`, `'linear'`, `'cubic'`, `'mitchell'`, `'lanczos2'`, `'lanczos3'` |
|
||||
| `withoutEnlargement` | boolean | `false` | Don't upscale |
|
||||
| `withoutReduction` | boolean | `false` | Don't downscale |
|
||||
| `fastShrinkOnLoad` | boolean | `true` | JPEG/WebP shrink-on-load |
|
||||
|
||||
**Fit modes:**
|
||||
- `cover` — crop to fill both dimensions
|
||||
- `contain` — letterbox within dimensions
|
||||
- `fill` — stretch to exact dimensions (ignores aspect ratio)
|
||||
- `inside` — fit within, no exceeding
|
||||
- `outside` — minimum size meeting both dimensions
|
||||
|
||||
**Position values:** `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`, `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `centre`/`center`
|
||||
|
||||
**Strategy (cover only):** `entropy`, `attention`
|
||||
|
||||
Only one resize per pipeline.
|
||||
|
||||
---
|
||||
|
||||
## Operations
|
||||
|
||||
### Rotation & Orientation
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `.rotate([angle], [options])` | Rotate by degrees; omit angle for EXIF auto-rotate. `options.background` for fill color |
|
||||
| `.autoOrient()` | Auto-orient from EXIF, then remove Orientation tag |
|
||||
| `.flip([flip])` | Vertical mirror (default `true`) |
|
||||
| `.flop([flop])` | Horizontal mirror (default `true`) |
|
||||
|
||||
### Transform
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `.affine(matrix, [options])` | 2x2 affine transform. Options: `background`, `idx`, `idy`, `odx`, `ody`, `interpolator` |
|
||||
| `.extend(extend)` | Add padding. Number for uniform, or `{ top, right, bottom, left, extendWith, background }`. `extendWith`: `'background'`, `'copy'`, `'repeat'`, `'mirror'` |
|
||||
| `.extract({ left, top, width, height })` | Crop region. Can be called before and/or after resize |
|
||||
| `.trim([options])` | Auto-crop to content. Options: `background` (default top-left pixel), `threshold` (default `10`), `lineArt` |
|
||||
|
||||
### Enhancement
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `.sharpen([options])` | Sharpen. `options.sigma` (0.000001-10), `.m1` (flat), `.m2` (jagged), `.x1`, `.y2`, `.y3` |
|
||||
| `.blur([options])` | No args: 3x3 box blur. `options.sigma` (0.3-1000) for Gaussian. Options: `precision`, `minAmplitude` |
|
||||
| `.median([size])` | Median filter, default 3x3 |
|
||||
| `.gamma([gamma], [gammaOut])` | Gamma correction (1.0-3.0, default 2.2) |
|
||||
| `.normalise([options])` | Stretch luminance. `options.lower` (default `1`), `.upper` (default `99`) percentiles |
|
||||
| `.clahe({ width, height, [maxSlope] })` | Contrast Limited Adaptive Histogram Equalization |
|
||||
|
||||
### Morphology
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `.dilate([width])` | Dilation, default 1px |
|
||||
| `.erode([width])` | Erosion, default 1px |
|
||||
|
||||
### Pixel Operations
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `.negate([options])` | Invert colors. `options.alpha` (default `true`) |
|
||||
| `.threshold([value], [options])` | Binarize at threshold (0-255, default 128). `options.greyscale` (default `true`) |
|
||||
| `.boolean(operand, operator)` | Bitwise op with another image: `'and'`, `'or'`, `'eor'` |
|
||||
| `.linear([a], [b])` | Per-channel linear transform: `a * pixel + b` |
|
||||
| `.recomb(matrix)` | 3x3 or 4x4 color recombination matrix |
|
||||
| `.modulate([options])` | Adjust `brightness` (multiply), `saturation` (multiply), `hue` (degrees), `lightness` (add) |
|
||||
| `.convolve(kernel)` | Custom convolution: `{ width, height, kernel, scale, offset }` |
|
||||
| `.flatten([options])` | Merge alpha with `options.background`, remove alpha |
|
||||
| `.unflatten()` | Add alpha; white becomes transparent (experimental) |
|
||||
|
||||
---
|
||||
|
||||
## Colour
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `.tint(color)` | Apply tint, preserving alpha |
|
||||
| `.greyscale([bool])` | Convert to 8-bit greyscale (alias: `.grayscale()`) |
|
||||
| `.pipelineColourspace(space)` | Set pipeline colorspace (e.g. `'rgb16'`, `'lab'`, `'grey16'`) |
|
||||
| `.toColourspace(space)` | Set output colorspace (e.g. `'srgb'`, `'cmyk'`, `'b-w'`) |
|
||||
|
||||
---
|
||||
|
||||
## Channel
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `.removeAlpha()` | Remove alpha channel |
|
||||
| `.ensureAlpha([alpha])` | Add alpha if missing. `alpha`: 0 (transparent) to 1 (opaque, default) |
|
||||
| `.extractChannel(channel)` | Extract single channel: `0`-`3` or `'red'`, `'green'`, `'blue'`, `'alpha'` |
|
||||
| `.joinChannel(images, [options])` | Add channel(s) from other image(s) |
|
||||
| `.bandbool(op)` | Bitwise across all bands: `'and'`, `'or'`, `'eor'` |
|
||||
|
||||
---
|
||||
|
||||
## Composite
|
||||
|
||||
```js
|
||||
.composite(images)
|
||||
```
|
||||
|
||||
Overlay images onto the pipeline image. `images` is an array of objects:
|
||||
|
||||
| Property | Type | Default | Description |
|
||||
|----------|------|---------|-------------|
|
||||
| `input` | Buffer \| string | -- | Image data, file path, or `create`/`text` object |
|
||||
| `blend` | string | `'over'` | Blend mode |
|
||||
| `gravity` | string | `'centre'` | Placement gravity |
|
||||
| `top` | number | -- | Pixel offset from top (overrides gravity) |
|
||||
| `left` | number | -- | Pixel offset from left (overrides gravity) |
|
||||
| `tile` | boolean | `false` | Repeat overlay across image |
|
||||
| `premultiplied` | boolean | `false` | Skip premultiplication |
|
||||
| `density` | number | `72` | DPI for vector overlays |
|
||||
|
||||
**Blend modes:** `over`, `multiply`, `screen`, `overlay`, `darken`, `lighten`, `hard-light`, `soft-light`, `difference`, `exclusion`, `colour-dodge`, `colour-burn`, `add`, `saturate`, `clear`, `source`, `in`, `out`, `atop`, `dest`, `dest-over`, `dest-in`, `dest-out`, `dest-atop`, `xor`
|
||||
|
||||
```js
|
||||
await sharp('base.png')
|
||||
.composite([{ input: 'overlay.png', gravity: 'southeast' }])
|
||||
.toFile('output.png');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output
|
||||
|
||||
### Write to File
|
||||
|
||||
```js
|
||||
await sharp('input.jpg').resize(800).toFile('output.jpg');
|
||||
```
|
||||
|
||||
Format inferred from extension. Returns `{ format, size, width, height, channels, premultiplied }`.
|
||||
|
||||
### Write to Buffer
|
||||
|
||||
```js
|
||||
const buffer = await sharp('input.jpg').resize(800).toBuffer();
|
||||
// or with info:
|
||||
const { data, info } = await sharp('input.jpg').resize(800).toBuffer({ resolveWithObject: true });
|
||||
```
|
||||
|
||||
### Format Methods
|
||||
|
||||
#### JPEG
|
||||
|
||||
```js
|
||||
.jpeg([options])
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `quality` | number | `80` | 1-100 |
|
||||
| `progressive` | boolean | `false` | Progressive JPEG |
|
||||
| `chromaSubsampling` | string | `'4:2:0'` | `'4:2:0'` or `'4:4:4'` |
|
||||
| `mozjpeg` | boolean | `false` | MozJPEG optimizations |
|
||||
| `force` | boolean | `true` | Force JPEG output |
|
||||
|
||||
#### PNG
|
||||
|
||||
```js
|
||||
.png([options])
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `progressive` | boolean | `false` | Progressive (interlace) |
|
||||
| `compressionLevel` | number | `6` | 0-9 |
|
||||
| `adaptiveFiltering` | boolean | `false` | Adaptive row filtering |
|
||||
| `palette` | boolean | `false` | Quantise to palette |
|
||||
| `quality` | number | `100` | Palette quality (1-100) |
|
||||
| `effort` | number | `7` | CPU effort (1-10, palette mode) |
|
||||
| `colours`/`colors` | number | `256` | Max palette colors (2-256) |
|
||||
| `dither` | number | `1.0` | Floyd-Steinberg dithering level |
|
||||
| `force` | boolean | `true` | Force PNG output |
|
||||
|
||||
#### WebP
|
||||
|
||||
```js
|
||||
.webp([options])
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `quality` | number | `80` | 1-100 |
|
||||
| `alphaQuality` | number | `100` | 0-100 |
|
||||
| `lossless` | boolean | `false` | Lossless compression |
|
||||
| `nearLossless` | boolean | `false` | Near-lossless mode |
|
||||
| `smartSubsample` | boolean | `false` | Smart chroma subsampling |
|
||||
| `preset` | string | `'default'` | `'default'`, `'photo'`, `'picture'`, `'drawing'`, `'icon'`, `'text'` |
|
||||
| `effort` | number | `4` | 0-6 |
|
||||
| `loop` | number | `0` | Animation loops (0 = infinite) |
|
||||
| `delay` | number \| Array | -- | Frame delay(s) in ms |
|
||||
| `force` | boolean | `true` | Force WebP output |
|
||||
|
||||
#### AVIF
|
||||
|
||||
```js
|
||||
.avif([options])
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `quality` | number | `50` | 1-100 |
|
||||
| `lossless` | boolean | `false` | Lossless mode |
|
||||
| `effort` | number | `4` | 0-9 |
|
||||
| `chromaSubsampling` | string | `'4:4:4'` | Chroma subsampling |
|
||||
| `bitdepth` | number | `8` | 8, 10, or 12 |
|
||||
|
||||
#### GIF
|
||||
|
||||
```js
|
||||
.gif([options])
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `reuse` | boolean | `true` | Reuse palette |
|
||||
| `progressive` | boolean | `false` | Progressive (interlace) |
|
||||
| `colours`/`colors` | number | `256` | 2-256 |
|
||||
| `effort` | number | `7` | 1-10 |
|
||||
| `dither` | number | `1.0` | 0-1 |
|
||||
| `loop` | number | `0` | 0 = infinite |
|
||||
| `delay` | number \| Array | -- | Frame delay(s) in ms |
|
||||
| `force` | boolean | `true` | Force GIF output |
|
||||
|
||||
#### TIFF
|
||||
|
||||
```js
|
||||
.tiff([options])
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `quality` | number | `80` | 1-100 |
|
||||
| `compression` | string | `'jpeg'` | `'none'`, `'jpeg'`, `'deflate'`, `'packbits'`, `'lzw'`, `'webp'`, `'zstd'`, `'jp2k'`, `'ccittfax4'` |
|
||||
| `predictor` | string | `'horizontal'` | `'none'`, `'horizontal'`, `'float'` |
|
||||
| `pyramid` | boolean | `false` | Write image pyramid |
|
||||
| `tile` | boolean | `false` | Tiled TIFF |
|
||||
| `tileWidth` | number | `256` | Tile width |
|
||||
| `tileHeight` | number | `256` | Tile height |
|
||||
| `bitdepth` | number | `8` | 1, 2, 4, or 8 |
|
||||
| `force` | boolean | `true` | Force TIFF output |
|
||||
|
||||
#### HEIF
|
||||
|
||||
```js
|
||||
.heif({ compression: 'hevc' })
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `compression` | string | required | `'av1'` or `'hevc'` |
|
||||
| `quality` | number | `50` | 1-100 |
|
||||
| `lossless` | boolean | `false` | Lossless mode |
|
||||
| `effort` | number | `4` | 0-9 |
|
||||
| `bitdepth` | number | `8` | 8, 10, or 12 |
|
||||
|
||||
#### Raw
|
||||
|
||||
```js
|
||||
.raw([options])
|
||||
```
|
||||
|
||||
- `options.depth` (string, default `'uchar'`): `'char'`, `'uchar'`, `'short'`, `'ushort'`, `'int'`, `'uint'`, `'float'`, `'double'`
|
||||
|
||||
#### Tile (DZI / Zoomify / IIIF)
|
||||
|
||||
```js
|
||||
.tile([options])
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `size` | number | `256` | Tile size (1-8192) |
|
||||
| `overlap` | number | `0` | Tile overlap (0-8192) |
|
||||
| `layout` | string | `'dz'` | `'dz'`, `'iiif'`, `'iiif3'`, `'zoomify'`, `'google'` |
|
||||
| `container` | string | `'fs'` | `'fs'` or `'zip'` |
|
||||
| `angle` | number | `0` | Rotation (multiple of 90) |
|
||||
| `background` | string \| Object | white | Fill color |
|
||||
|
||||
---
|
||||
|
||||
## Metadata & Stats
|
||||
|
||||
### metadata()
|
||||
|
||||
```js
|
||||
const meta = await sharp('input.jpg').metadata();
|
||||
```
|
||||
|
||||
Returns without decoding pixels:
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `format` | string | `'jpeg'`, `'png'`, `'webp'`, `'gif'`, `'svg'`, etc. |
|
||||
| `width` | number | Pixel width |
|
||||
| `height` | number | Pixel height |
|
||||
| `space` | string | Color space (`'srgb'`, `'rgb'`, `'cmyk'`, `'b-w'`, etc.) |
|
||||
| `channels` | number | Band count |
|
||||
| `depth` | string | Pixel depth (`'uchar'`, `'ushort'`, `'float'`, etc.) |
|
||||
| `density` | number | DPI |
|
||||
| `chromaSubsampling` | string | e.g. `'4:2:0'` |
|
||||
| `isProgressive` | boolean | Progressive/interlaced |
|
||||
| `hasAlpha` | boolean | Has alpha channel |
|
||||
| `hasProfile` | boolean | Has ICC profile |
|
||||
| `orientation` | number | EXIF orientation (1-8) |
|
||||
| `pages` | number | Page count |
|
||||
| `size` | number | Total bytes (Buffer/Stream input) |
|
||||
| `exif` | Buffer | Raw EXIF |
|
||||
| `icc` | Buffer | ICC profile |
|
||||
| `xmp` | Buffer | XMP data |
|
||||
|
||||
### stats()
|
||||
|
||||
```js
|
||||
const stats = await sharp('input.jpg').stats();
|
||||
```
|
||||
|
||||
Returns pixel-derived statistics:
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `channels` | Array | Per-channel: `min`, `max`, `sum`, `mean`, `stdev`, `minX`, `minY`, `maxX`, `maxY` |
|
||||
| `isOpaque` | boolean | Fully opaque |
|
||||
| `entropy` | number | Greyscale entropy |
|
||||
| `sharpness` | number | Laplacian sharpness |
|
||||
| `dominant` | Object | Dominant sRGB color |
|
||||
|
||||
---
|
||||
|
||||
## Metadata Preservation
|
||||
|
||||
By default, sharp strips all metadata and converts to sRGB.
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `.keepMetadata()` | Preserve all metadata (EXIF, ICC, XMP, IPTC) |
|
||||
| `.keepExif()` | Preserve EXIF only |
|
||||
| `.withExif(exif)` | Set EXIF (replaces input). Object keyed by IFD |
|
||||
| `.withExifMerge(exif)` | Merge with existing EXIF |
|
||||
| `.keepIccProfile()` | Preserve ICC profile |
|
||||
| `.withIccProfile(icc, [options])` | Set ICC: path or `'srgb'`, `'p3'`, `'cmyk'` |
|
||||
| `.keepXmp()` | Preserve XMP |
|
||||
| `.withXmp(xmp)` | Set XMP (XML string) |
|
||||
| `.withMetadata([options])` | Preserve most metadata. Options: `orientation`, `density` |
|
||||
|
||||
---
|
||||
|
||||
## Timeout
|
||||
|
||||
```js
|
||||
.timeout({ seconds: 30 })
|
||||
```
|
||||
|
||||
Abort processing after N seconds. `0` = no timeout (default).
|
||||
|
||||
---
|
||||
|
||||
## Utility (Static)
|
||||
|
||||
| Property/Method | Description |
|
||||
|-----------------|-------------|
|
||||
| `sharp.format` | Object with available input/output format booleans |
|
||||
| `sharp.versions` | Version info for sharp, libvips, dependencies |
|
||||
| `sharp.interpolators` | Enum: `nearest`, `bilinear`, `bicubic`, `lbb`, `nohalo`, `vsqbs` |
|
||||
| `sharp.cache([options])` | Get/set cache: `{ memory: 50, files: 20, items: 100 }` |
|
||||
| `sharp.concurrency([n])` | Get/set thread count (default: CPU cores) |
|
||||
| `sharp.counters()` | Returns `{ queue, process }` |
|
||||
| `sharp.simd([bool])` | Enable/disable SIMD (default `true`) |
|
||||
| `sharp.block({ operation })` | Block specific operations |
|
||||
| `sharp.unblock({ operation })` | Unblock operations |
|
||||
|
||||
---
|
||||
|
||||
## Common Recipes
|
||||
|
||||
### Resize and convert format
|
||||
|
||||
```js
|
||||
await sharp('input.png')
|
||||
.resize(800, 600)
|
||||
.webp({ quality: 80 })
|
||||
.toFile('output.webp');
|
||||
```
|
||||
|
||||
### Resize to fit within bounds (no upscale)
|
||||
|
||||
```js
|
||||
await sharp('input.jpg')
|
||||
.resize(1200, 800, { fit: 'inside', withoutEnlargement: true })
|
||||
.toFile('output.jpg');
|
||||
```
|
||||
|
||||
### Create thumbnail (cover crop)
|
||||
|
||||
```js
|
||||
await sharp('input.jpg')
|
||||
.resize(250, 250, { fit: 'cover', position: 'attention' })
|
||||
.toFile('thumb.jpg');
|
||||
```
|
||||
|
||||
### Crop region
|
||||
|
||||
```js
|
||||
await sharp('input.jpg')
|
||||
.extract({ left: 100, top: 50, width: 400, height: 300 })
|
||||
.toFile('cropped.jpg');
|
||||
```
|
||||
|
||||
### Add watermark overlay
|
||||
|
||||
```js
|
||||
await sharp('photo.jpg')
|
||||
.composite([{ input: 'watermark.png', gravity: 'southeast' }])
|
||||
.toFile('watermarked.jpg');
|
||||
```
|
||||
|
||||
### Composite text overlay
|
||||
|
||||
```js
|
||||
await sharp('photo.jpg')
|
||||
.composite([{
|
||||
input: { text: { text: 'Hello World', font: 'sans', dpi: 200, rgba: true } },
|
||||
gravity: 'south'
|
||||
}])
|
||||
.toFile('annotated.jpg');
|
||||
```
|
||||
|
||||
### Convert to greyscale
|
||||
|
||||
```js
|
||||
await sharp('input.jpg')
|
||||
.greyscale()
|
||||
.toFile('grey.jpg');
|
||||
```
|
||||
|
||||
### Blur
|
||||
|
||||
```js
|
||||
await sharp('input.jpg')
|
||||
.blur({ sigma: 5 })
|
||||
.toFile('blurred.jpg');
|
||||
```
|
||||
|
||||
### Rotate
|
||||
|
||||
```js
|
||||
await sharp('input.jpg')
|
||||
.rotate(90)
|
||||
.toFile('rotated.jpg');
|
||||
```
|
||||
|
||||
### Auto-orient from EXIF
|
||||
|
||||
```js
|
||||
await sharp('input.jpg')
|
||||
.autoOrient()
|
||||
.toFile('oriented.jpg');
|
||||
```
|
||||
|
||||
### Extend with padding
|
||||
|
||||
```js
|
||||
await sharp('input.png')
|
||||
.extend({ top: 20, bottom: 20, left: 20, right: 20, background: '#ffffff' })
|
||||
.toFile('padded.png');
|
||||
```
|
||||
|
||||
### Auto-trim whitespace
|
||||
|
||||
```js
|
||||
await sharp('input.png')
|
||||
.trim({ threshold: 10 })
|
||||
.toFile('trimmed.png');
|
||||
```
|
||||
|
||||
### Optimize JPEG for web
|
||||
|
||||
```js
|
||||
await sharp('input.jpg')
|
||||
.resize(1920, null, { withoutEnlargement: true })
|
||||
.jpeg({ quality: 75, mozjpeg: true, progressive: true })
|
||||
.toFile('optimized.jpg');
|
||||
```
|
||||
|
||||
### Generate AVIF from JPEG
|
||||
|
||||
```js
|
||||
await sharp('input.jpg')
|
||||
.avif({ quality: 50, effort: 4 })
|
||||
.toFile('output.avif');
|
||||
```
|
||||
|
||||
### Extract channel
|
||||
|
||||
```js
|
||||
await sharp('input.png')
|
||||
.extractChannel('red')
|
||||
.toFile('red-channel.png');
|
||||
```
|
||||
|
||||
### Get image metadata
|
||||
|
||||
```js
|
||||
const { width, height, format, space } = await sharp('input.jpg').metadata();
|
||||
```
|
||||
|
||||
### Buffer round-trip
|
||||
|
||||
```js
|
||||
const buffer = await sharp('input.jpg')
|
||||
.resize(300)
|
||||
.png()
|
||||
.toBuffer();
|
||||
```
|
||||
|
||||
### Create solid color image
|
||||
|
||||
```js
|
||||
await sharp({ create: { width: 100, height: 100, channels: 4, background: '#ff6600' } })
|
||||
.png()
|
||||
.toFile('orange.png');
|
||||
```
|
||||
|
||||
### Join images into grid
|
||||
|
||||
```js
|
||||
await sharp(['a.png', 'b.png', 'c.png', 'd.png'], { join: { across: 2 } })
|
||||
.toFile('grid.png');
|
||||
```
|
||||
|
||||
### Preserve metadata
|
||||
|
||||
```js
|
||||
await sharp('input.jpg')
|
||||
.resize(800)
|
||||
.keepMetadata()
|
||||
.toFile('output.jpg');
|
||||
```
|
||||
|
||||
### Animated GIF resize
|
||||
|
||||
```js
|
||||
await sharp('input.gif', { animated: true })
|
||||
.resize(200)
|
||||
.gif()
|
||||
.toFile('small.gif');
|
||||
```
|
||||
|
||||
### Multiple outputs from one input
|
||||
|
||||
```js
|
||||
const pipeline = sharp('input.jpg');
|
||||
await Promise.all([
|
||||
pipeline.clone().resize(200).toFile('thumb.jpg'),
|
||||
pipeline.clone().resize(800).toFile('medium.jpg'),
|
||||
pipeline.clone().resize(1600).toFile('large.jpg'),
|
||||
]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Source
|
||||
|
||||
- Repository: https://github.com/lovell/sharp
|
||||
- Documentation: https://sharp.pixelplumbing.com
|
||||
- API — Constructor: https://sharp.pixelplumbing.com/api-constructor
|
||||
- API — Input: https://sharp.pixelplumbing.com/api-input
|
||||
- API — Resize: https://sharp.pixelplumbing.com/api-resize
|
||||
- API — Operations: https://sharp.pixelplumbing.com/api-operation
|
||||
- API — Colour: https://sharp.pixelplumbing.com/api-colour
|
||||
- API — Channel: https://sharp.pixelplumbing.com/api-channel
|
||||
- API — Composite: https://sharp.pixelplumbing.com/api-composite
|
||||
- API — Output: https://sharp.pixelplumbing.com/api-output
|
||||
- API — Utility: https://sharp.pixelplumbing.com/api-utility
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"id":"36336dc9-e6e5-49c2-8a5b-a972001f95ce"}
|
||||
@@ -0,0 +1,173 @@
|
||||
---
|
||||
name: whisper.cpp
|
||||
description: Transcribe audio files to text using whisper.cpp. Use when the user wants to transcribe audio, convert speech to text, or extract text from an audio/video file.
|
||||
---
|
||||
|
||||
# Whisper.cpp
|
||||
|
||||
API reference for the whisper.cpp HTTP server running at `http://macmini:8178`.
|
||||
|
||||
whisper.cpp is a C/C++ port of OpenAI's Whisper speech recognition model. The server accepts audio files via HTTP and returns transcriptions in various formats.
|
||||
|
||||
## Server
|
||||
|
||||
- **Base URL:** `http://macmini:8178`
|
||||
- **No authentication required**
|
||||
|
||||
## Endpoints
|
||||
|
||||
### POST /inference
|
||||
|
||||
Transcribes an audio file. Accepts `multipart/form-data`.
|
||||
|
||||
#### Example
|
||||
|
||||
```bash
|
||||
curl -s http://macmini:8178/inference \
|
||||
-F file="@/path/to/audio.mp3" \
|
||||
-F temperature="0.0" \
|
||||
-F temperature_inc="0.2" \
|
||||
-F response_format="json"
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
##### File (required)
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `file` | file | Audio file to transcribe. Accepts at least WAV and MP3. |
|
||||
|
||||
##### Response Format
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `response_format` | string | `json` | Output format: `json`, `verbose_json` (or `vjson`), `text`, `srt`, `vtt` |
|
||||
|
||||
##### Language
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `language` | string | `en` | Spoken language code (e.g. `en`, `pt`, `es`, `fr`). Use `auto` for auto-detection. |
|
||||
| `detect_language` | bool | `false` | Exit after detecting the language (no transcription). |
|
||||
| `translate` | bool | `false` | Translate from source language to English. |
|
||||
|
||||
##### Decoding
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `temperature` | float | `0.0` | Sampling temperature. `0.0` is deterministic. |
|
||||
| `temperature_inc` | float | `0.2` | Temperature increment on fallback attempts. |
|
||||
| `best_of` | int | `2` | Number of candidate decodings to keep. |
|
||||
| `beam_size` | int | `-1` | Beam search size. `-1` disables beam search. |
|
||||
| `entropy_thold` | float | `2.40` | Entropy threshold — decoder fails and retries if exceeded. |
|
||||
| `logprob_thold` | float | `-1.00` | Log probability threshold for decoder failure. |
|
||||
| `no_fallback` | bool | `false` | Disable temperature fallback on decode failure. |
|
||||
|
||||
##### Segmentation
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `max_len` | int | `0` | Maximum segment length in characters. `0` for unlimited. |
|
||||
| `max_context` | int | `-1` | Maximum text context tokens to store. `-1` for unlimited. |
|
||||
| `split_on_word` | bool | `false` | Split segments at word boundaries instead of token boundaries. |
|
||||
| `no_timestamps` | bool | `false` | Suppress timestamps in output. |
|
||||
| `word_thold` | float | `0.01` | Word timestamp probability threshold. |
|
||||
|
||||
##### Audio Processing
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `offset_t` | int | `0` | Time offset in milliseconds — skip this much audio from the start. |
|
||||
| `offset_n` | int | `0` | Segment index offset. |
|
||||
| `duration` | int | `0` | Duration of audio to process in milliseconds. `0` for all. |
|
||||
| `audio_ctx` | int | `0` | Audio context size. `0` for all. |
|
||||
|
||||
##### Speaker Diarization
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `diarize` | bool | `false` | Enable speaker diarization (requires stereo audio). |
|
||||
| `tinydiarize` | bool | `false` | Enable tinydiarize (requires a tdrz model). |
|
||||
|
||||
##### Voice Activity Detection (VAD)
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `vad` | bool | `false` | Enable VAD preprocessing. |
|
||||
| `vad_threshold` | float | `0.50` | Speech confidence threshold (0.0–1.0). |
|
||||
| `vad_min_speech_duration_ms` | int | `250` | Minimum speech segment duration in ms. |
|
||||
| `vad_min_silence_duration_ms` | int | `100` | Minimum silence duration to split segments. |
|
||||
| `vad_max_speech_duration_s` | float | `FLT_MAX` | Auto-split segments longer than this (seconds). |
|
||||
| `vad_speech_pad_ms` | int | `30` | Padding added around speech segments (ms). |
|
||||
| `vad_samples_overlap` | float | `0.10` | Overlap between segments (seconds). |
|
||||
|
||||
##### Other
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `prompt` | string | `""` | Initial prompt to condition the model (e.g. for vocabulary hints). |
|
||||
| `suppress_nst` | bool | `false` | Suppress non-speech tokens. |
|
||||
| `no_context` | bool | `false` | Do not use previous audio context for subsequent segments. |
|
||||
| `debug_mode` | bool | `false` | Enable debug output. |
|
||||
|
||||
#### Response Formats
|
||||
|
||||
##### `json` (default)
|
||||
|
||||
Minimal JSON with just the transcribed text.
|
||||
|
||||
```json
|
||||
{"text": "The transcribed content goes here."}
|
||||
```
|
||||
|
||||
##### `verbose_json` (or `vjson`)
|
||||
|
||||
Extended JSON including task type, language, audio duration, per-segment timestamps, token-level timing, confidence scores, and language probability distribution.
|
||||
|
||||
##### `text`
|
||||
|
||||
Plain text transcription. Includes speaker labels if diarization is enabled.
|
||||
|
||||
##### `srt`
|
||||
|
||||
SubRip subtitle format with sequential numbering, `HH:MM:SS,mmm` timestamps, and text content.
|
||||
|
||||
```
|
||||
1
|
||||
00:00:00,000 --> 00:00:03,500
|
||||
The transcribed content goes here.
|
||||
```
|
||||
|
||||
##### `vtt`
|
||||
|
||||
WebVTT subtitle format with `WEBVTT` header and `HH:MM:SS.mmm` timestamps.
|
||||
|
||||
```
|
||||
WEBVTT
|
||||
|
||||
00:00:00.000 --> 00:00:03.500
|
||||
The transcribed content goes here.
|
||||
```
|
||||
|
||||
### POST /load
|
||||
|
||||
Loads a different model file on the server at runtime.
|
||||
|
||||
```bash
|
||||
curl -s http://macmini:8178/load \
|
||||
-F model="/path/to/model.bin"
|
||||
```
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `model` | string | Path to the model file on the server. |
|
||||
|
||||
## Supported Audio Formats
|
||||
|
||||
The server accepts at least WAV (16-bit PCM) and MP3 files directly. If the server was started with `--convert`, it can use ffmpeg to handle additional formats (ogg, flac, m4a, etc.).
|
||||
|
||||
## Source
|
||||
|
||||
- Repository: https://github.com/ggml-org/whisper.cpp
|
||||
- Server docs: https://github.com/ggml-org/whisper.cpp/blob/master/examples/server/README.md
|
||||
@@ -0,0 +1,103 @@
|
||||
# Tasks
|
||||
|
||||
A task is a set of instructions to accomplish an atomic goal. Each task lives in its own directory under `tasks/` and is defined by a `TASK.md` file.
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
tasks/
|
||||
<task-slug>/
|
||||
TASK.md
|
||||
```
|
||||
|
||||
## TASK.md Format
|
||||
|
||||
A task file has two parts: **frontmatter** (YAML metadata) and **body** (Markdown instructions).
|
||||
|
||||
### Frontmatter
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: Task Name
|
||||
description: A short description of what the task does.
|
||||
version: 1
|
||||
author: pastilhas
|
||||
tags:
|
||||
- tag1
|
||||
- tag2
|
||||
skills:
|
||||
- skill-name
|
||||
trigger:
|
||||
- type: file
|
||||
extensions:
|
||||
- ext1
|
||||
- ext2
|
||||
- type: directory
|
||||
inputs:
|
||||
- name: input_name
|
||||
description: What this input is.
|
||||
required: true
|
||||
---
|
||||
```
|
||||
|
||||
#### Fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `name` | string | yes | Human-readable name of the task. |
|
||||
| `description` | string | yes | Short description of what the task does. |
|
||||
| `version` | integer | no | Version number of the task definition. |
|
||||
| `author` | string | no | Author of the task. |
|
||||
| `tags` | string[] | no | Tags for categorization. |
|
||||
| `skills` | string[] | no | Skills required to execute the task. |
|
||||
| `trigger` | object[] | no | List of triggers that define when this task is applicable. |
|
||||
| `trigger[].type` | string | yes | What the trigger applies to (`file` or `directory`). |
|
||||
| `trigger[].extensions` | string[] | no | File extensions that match this trigger. Only applicable when `type` is `file`. |
|
||||
| `inputs` | object[] | no | Inputs the task expects. |
|
||||
| `inputs[].name` | string | yes | Name of the input parameter. |
|
||||
| `inputs[].description` | string | yes | Description of the input. |
|
||||
| `inputs[].required` | boolean | no | Whether the input is required. |
|
||||
|
||||
### Body
|
||||
|
||||
The body contains:
|
||||
|
||||
1. **Title** — `# Task Name`, matching the frontmatter `name`.
|
||||
2. **Description** — A one-line summary, matching the frontmatter `description`.
|
||||
3. **Steps** — An ordered list under `## Steps` describing the instructions to accomplish the task.
|
||||
|
||||
### Example
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: Transcribe Audio File
|
||||
description: Transcribe an audio file to text using whisper.cpp.
|
||||
version: 1
|
||||
author: pastilhas
|
||||
tags:
|
||||
- audio
|
||||
- transcription
|
||||
skills:
|
||||
- whisper.cpp
|
||||
trigger:
|
||||
- type: file
|
||||
extensions:
|
||||
- mp3
|
||||
- wav
|
||||
- m4a
|
||||
inputs:
|
||||
- name: file_path
|
||||
description: Path to the audio file to transcribe.
|
||||
required: true
|
||||
---
|
||||
|
||||
# Transcribe Audio File
|
||||
|
||||
Transcribe an audio file to text using whisper.cpp.
|
||||
|
||||
## Steps
|
||||
|
||||
1. First step.
|
||||
2. Second step.
|
||||
3. Third step.
|
||||
```
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
name: Convert To MP3
|
||||
description: Convert audio files to MP3 320kbps, preserving metadata.
|
||||
version: 1
|
||||
author: pastilhas
|
||||
tags:
|
||||
- audio
|
||||
- conversion
|
||||
skills:
|
||||
- convert-audio-to-mp3
|
||||
trigger:
|
||||
- type: file
|
||||
extensions:
|
||||
- flac
|
||||
- wav
|
||||
- ogg
|
||||
- wma
|
||||
- aac
|
||||
- m4a
|
||||
- opus
|
||||
- aiff
|
||||
- aif
|
||||
- ape
|
||||
- wv
|
||||
- alac
|
||||
- dsf
|
||||
- dff
|
||||
- type: directory
|
||||
inputs:
|
||||
- name: file_path
|
||||
description: Path to an audio file or an artist directory to convert.
|
||||
required: true
|
||||
---
|
||||
|
||||
# Convert To MP3
|
||||
|
||||
Convert audio files to MP3 320kbps, preserving metadata.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Determine whether `file_path` points to a single audio file or a directory.
|
||||
2. If it is a single file, use the Convert Audio To MP3 skill's single-file script to convert it. The source file is deleted on success.
|
||||
3. If it is a directory, use the Convert Audio To MP3 skill's batch script with the directory name as the artist name. All audio files within subdirectories are converted recursively.
|
||||
4. Verify the conversion completed successfully and report the result to the user.
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"id":"12f6c028-f2b8-4461-83cf-6ed8eb6bd3c9"}
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
name: Transcribe Audio File
|
||||
description: Transcribe an audio file to text using whisper.cpp.
|
||||
version: 1
|
||||
author: pastilhas
|
||||
tags:
|
||||
- audio
|
||||
- transcription
|
||||
skills:
|
||||
- whisper.cpp
|
||||
trigger:
|
||||
- type: file
|
||||
extensions:
|
||||
- mp3
|
||||
- wav
|
||||
- m4a
|
||||
inputs:
|
||||
- name: file_path
|
||||
description: Path to the audio file to transcribe.
|
||||
required: true
|
||||
---
|
||||
|
||||
# Transcribe Audio File
|
||||
|
||||
Transcribe an audio file to text using whisper.cpp.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Determine the user's root directory by navigating one level up from the current working directory. Read `settings.json` from the root directory and extract the `languages` section.
|
||||
2. Detect the language of the audio file using the whisper.cpp skill with `detect_language=true` and `response_format=verbose_json`.
|
||||
3. Compare the detected language against the user's `languages.spoken` list. If the detected language is in the list, skip translation. Otherwise, set `translate=true`.
|
||||
4. Use the whisper.cpp skill to transcribe the audio file at `file_path`, passing the detected language as the `language` parameter and the `translate` flag from the previous step.
|
||||
5. Read the transcription and generate a short, descriptive title based on its contents.
|
||||
6. Create a directory alongside the original audio file named `<date>_<slug>`, where `<date>` is the current date in `YYYYMMDD` format and `<slug>` is a slug derived from the generated title.
|
||||
7. Move the original audio file and save the transcription as a Markdown file (`.md`) into the new directory, using the same base name for the `.md` file.
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"id":"2dfd2db0-9f36-414b-8639-16918d98448c"}
|
||||
Reference in New Issue
Block a user