Token导航 LogoToken导航TokenDH.com
前端设计只读github未标认证来源可访问许可证需确认审计通过

obs-audio-plugin-writingobs 音频插件编写

Agent Skill

用于辅助文档、README、Markdown、说明文和内容稿件的整理与改写。它适合让 Agent 提炼结构、补齐章节、统一术语、检查链接或把零散材料整理成可读文档。使用时应保留项目已有事实、命令和路径,不要把未确认的信息写成确定结论;涉及对外文案时,还需要控制语气,避免过度营销或夸大能力。

总安装

242

周安装

10

GitHub Stars

3

下载量

79
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:obs-audio-plugin-writing(obs 音频插件编写)
来源仓库:https://github.com/meriley/claude-code-skills
仓库路径:skills/obs-audio-plugin-writing
安装命令:
npx skills add https://github.com/meriley/claude-code-skills --skill obs-audio-plugin-writing
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/meriley/claude-code-skills --skill obs-audio-plugin-writing

简介

辅助整理文档、README 和内容稿件,提升结构化表达能力。

  • 适合在 Markdown 和说明文中提炼章节、统一术语或检查链接。
  • 通过 npx skills add 命令从 GitHub 安装并使用。
  • 应保留项目已有事实,避免将未确认信息写成确定结论。
  • obs-audio-plugin-writing 属于前端设计类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

OBS Audio Plugin Development

Purpose

Develop OBS Studio audio plugins including audio sources (generators, capture) and audio filters (gain, EQ, compression). Covers real-time audio processing patterns, the filter_audio callback, and audio-specific settings.

When NOT to Use

  • Video plugins → Use obs-plugin-developing (future skills)
  • Output/encoder plugins → Use obs-plugin-developing
  • Code review → Use obs-plugin-reviewing

Quick Start: Audio Filter in 5 Steps

Step 1: Create Plugin Structure

#include <obs-module.h>
#include <media-io/audio-math.h>  /* For db_to_mul, mul_to_db */

OBS_DECLARE_MODULE()
OBS_MODULE_USE_DEFAULT_LOCALE("my-audio-filter", "en-US")

/* Forward declaration */
extern struct obs_source_info my_audio_filter;

bool obs_module_load(void)
{
    obs_register_source(&my_audio_filter);
    return true;
}

Step 2: Define Context Structure

struct filter_data {
    obs_source_t *context;    /* Required: Reference to this filter */
    size_t channels;          /* Number of audio channels */
    float gain;               /* Gain multiplier (linear, not dB) */
};

Step 3: Implement Core Callbacks

static const char *filter_name(void *unused)
{
    UNUSED_PARAMETER(unused);
    return obs_module_text("MyAudioFilter");
}

static void *filter_create(obs_data_t *settings, obs_source_t *filter)
{
    struct filter_data *ctx = bzalloc(sizeof(*ctx));
    ctx->context = filter;
    filter_update(ctx, settings);  /* Apply initial settings */
    return ctx;
}

static void filter_destroy(void *data)
{
    struct filter_data *ctx = data;
    bfree(ctx);  /* CRITICAL: Always free allocated memory */
}

static void filter_update(void *data, obs_data_t *settings)
{
    struct filter_data *ctx = data;
    double db = obs_data_get_double(settings, "gain_db");
    ctx->gain = db_to_mul((float)db);
    ctx->channels = audio_output_get_channels(obs_get_audio());
}

Step 4: Implement filter_audio Callback

static struct obs_audio_data *filter_audio(void *data,
                                           struct obs_audio_data *audio)
{
    struct filter_data *ctx = data;
    float **adata = (float **)audio->data;

    for (size_t c = 0; c < ctx->channels; c++) {
        if (audio->data[c]) {  /* CRITICAL: Check channel exists */
            for (size_t i = 0; i < audio->frames; i++) {
                adata[c][i] *= ctx->gain;
            }
        }
    }
    return audio;
}

Step 5: Define Settings & Properties

static void filter_defaults(obs_data_t *settings)
{
    obs_data_set_default_double(settings, "gain_db", 0.0);
}

static obs_properties_t *filter_properties(void *data)
{
    UNUSED_PARAMETER(data);
    obs_properties_t *props = obs_properties_create();

    obs_property_t *p = obs_properties_add_float_slider(
        props, "gain_db", obs_module_text("Gain"),
        -30.0, 30.0, 0.1);
    obs_property_float_set_suffix(p, " dB");

    return props;
}

Step 6: Register the Filter

struct obs_source_info my_audio_filter = {
    .id = "my_audio_filter",
    .type = OBS_SOURCE_TYPE_FILTER,
    .output_flags = OBS_SOURCE_AUDIO,
    .get_name = filter_name,
    .create = filter_create,
    .destroy = filter_destroy,
    .update = filter_update,
    .filter_audio = filter_audio,
    .get_defaults = filter_defaults,
    .get_properties = filter_properties,
};

Audio Source Development

Audio sources generate or capture audio and push it to OBS.

Audio Source Structure

struct source_data {
    obs_source_t *source;
    pthread_t thread;
    os_event_t *event;
    bool active;
    uint64_t timestamp;
};

Audio Source Registration

struct obs_source_info my_audio_source = {
    .id = "my_audio_source",
    .type = OBS_SOURCE_TYPE_INPUT,
    .output_flags = OBS_SOURCE_AUDIO,
    .get_name = source_name,
    .create = source_create,
    .destroy = source_destroy,
    /* Audio sources typically don't need filter_audio */
    /* Instead, they push audio via obs_source_output_audio() */
};

Pushing Audio Data

static void push_audio(struct source_data *ctx, uint8_t *buffer, size_t frames)
{
    struct obs_source_audio audio = {
        .data[0] = buffer,
        .frames = frames,
        .speakers = SPEAKERS_MONO,        /* Or SPEAKERS_STEREO, etc. */
        .samples_per_sec = 48000,
        .timestamp = ctx->timestamp,
        .format = AUDIO_FORMAT_FLOAT_PLANAR,
    };

    obs_source_output_audio(ctx->source, &audio);
    ctx->timestamp += (uint64_t)frames * 1000000000ULL / 48000;
}

Audio Data Structures

obs_audio_data (Filter Input)

struct obs_audio_data {
    uint8_t *data[MAX_AV_PLANES];  /* Audio channel data */
    uint32_t frames;               /* Number of audio frames */
    uint64_t timestamp;            /* Timestamp in nanoseconds */
};

obs_source_audio (Source Output)

struct obs_source_audio {
    const uint8_t *data[MAX_AV_PLANES];
    uint32_t frames;
    enum speaker_layout speakers;
    enum audio_format format;
    uint32_t samples_per_sec;
    uint64_t timestamp;
};

Speaker Layouts

ConstantChannelsDescription
SPEAKERS_MONO1Single channel
SPEAKERS_STEREO2Left, Right
SPEAKERS_2POINT13L, R, LFE
SPEAKERS_4POINT04L, R, C, S
SPEAKERS_4POINT15L, R, C, LFE, S
SPEAKERS_5POINT16L, R, C, LFE, SL, SR
SPEAKERS_7POINT18L, R, C, LFE, SL, SR, BL, BR

Audio Formats

ConstantTypeDescription
AUDIO_FORMAT_U8BITuint8_tUnsigned 8-bit
AUDIO_FORMAT_16BITint16_tSigned 16-bit
AUDIO_FORMAT_32BITint32_tSigned 32-bit
AUDIO_FORMAT_FLOATfloat32-bit float interleaved
AUDIO_FORMAT_FLOAT_PLANARfloat32-bit float planar

Audio Math Functions

Include <media-io/audio-math.h> for these utilities:

/* Convert decibels to linear multiplier */
float db_to_mul(float db);
/* Example: db_to_mul(-6.0) ≈ 0.5 (half volume) */

/* Convert linear multiplier to decibels */
float mul_to_db(float mul);
/* Example: mul_to_db(0.5) ≈ -6.0 dB */

Audio Properties UI

Gain Slider (dB)

obs_property_t *p = obs_properties_add_float_slider(
    props, "gain_db", "Gain", -30.0, 30.0, 0.1);
obs_property_float_set_suffix(p, " dB");

Channel Selector

obs_property_t *ch = obs_properties_add_list(
    props, "channel", "Channel",
    OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_property_list_add_int(ch, "All", -1);
obs_property_list_add_int(ch, "Left", 0);
obs_property_list_add_int(ch, "Right", 1);

Frequency Selector

obs_property_t *freq = obs_properties_add_int_slider(
    props, "frequency", "Frequency (Hz)", 20, 20000, 1);
obs_property_int_set_suffix(freq, " Hz");

FORBIDDEN Patterns

Critical Violations

PatternProblemSolution
Missing OBS_DECLARE_MODULE()Plugin won't loadAdd macro at file start
return false from obs_module_load()Plugin fails silentlyReturn true on success
Missing bfree() in destroyMemory leakAlways free context
Global stateThread safety issuesUse context struct
Blocking in filter_audioAudio glitchesNever block/wait
Ignoring NULL channelsCrashCheck audio->data[c]
Ignoring audio->framesBuffer overflowAlways use frame count
Malloc in filter_audioPerformance issuesPre-allocate buffers

Anti-Pattern Examples

/* BAD: Global state */
static float g_gain = 1.0;  /* WRONG - not thread safe */

/* GOOD: Context structure */
struct filter_data {
    float gain;  /* Per-instance state */
};

/* BAD: Ignoring NULL channels */
for (size_t c = 0; c < channels; c++) {
    adata[c][i] *= gain;  /* CRASH if channel doesn't exist */
}

/* GOOD: Check channel exists */
for (size_t c = 0; c < channels; c++) {
    if (audio->data[c]) {  /* Check first */
        adata[c][i] *= gain;
    }
}

/* BAD: Blocking in audio callback */
static struct obs_audio_data *filter_audio(void *data, struct obs_audio_data *audio)
{
    pthread_mutex_lock(&mutex);  /* WRONG - can cause glitches */
    /* ... */
}

/* GOOD: Use atomic operations or lock-free structures */

Common Pitfalls

ProblemCauseSolution
No audio outputWrong output_flagsUse OBS_SOURCE_AUDIO
Filter not appliedMissing filter_audio callbackImplement callback
Crackles/popsBlocking in audio threadNever block
Volume too loudUsing dB directlyConvert with db_to_mul()
Mono onlyHardcoded channel countUse audio_output_get_channels()
Settings not savedMissing get_defaultsImplement defaults callback

Thread Safety

The filter_audio callback runs on the audio thread, separate from the main thread.

Rules:

  1. Never block (no mutexes, no I/O, no allocations)
  2. Use atomic operations for shared state
  3. Pre-allocate all buffers in create callback
  4. Configuration changes happen in update (main thread)
/* Safe pattern: atomic gain update */
#include <stdatomic.h>

struct filter_data {
    atomic_int gain_int;  /* Store gain * 1000 as int */
};

static void filter_update(void *data, obs_data_t *settings)
{
    struct filter_data *ctx = data;
    double db = obs_data_get_double(settings, "gain_db");
    int gain_scaled = (int)(db_to_mul((float)db) * 1000);
    atomic_store(&ctx->gain_int, gain_scaled);
}

static struct obs_audio_data *filter_audio(void *data, struct obs_audio_data *audio)
{
    struct filter_data *ctx = data;
    float gain = atomic_load(&ctx->gain_int) / 1000.0f;
    /* ... process audio ... */
}

External Documentation

Context7 (Real-time docs)

mcp__context7__get-library-docs
context7CompatibleLibraryID: "/obsproject/obs-studio"
topic: "audio filter plugin filter_audio"

Official References

Related Files

  • REFERENCE.md - Complete API documentation
  • TEMPLATES.md - Ready-to-use code templates

Related Skills

  • obs-plugin-developing - Plugin types overview, build system
  • obs-plugin-reviewing - Code review checklist

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

33.94%
按下载量换算27

Claude

30.71%
按下载量换算24

Cursor

16.63%
按下载量换算13

Gemini CLI

9.02%
按下载量换算7

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

只读

该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills