Token导航 LogoToken导航

Agent Skill · 前端设计

audio-producer(音频制作人)

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

audio-producer 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为权限未标注;许可证为 MIT,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 1,902。

总安装 3,374周安装 142GitHub Stars 26下载 1,181核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

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

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

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/daffy0208/ai-dev-standards --skill audio-producer

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

用于构建网页音频播放器、处理音频效果和创建交互式声音体验。支持自定义播放器组件、波形可视化、音频特效和实时操作。适用于需要动态音频交互的前端项目,如游戏音效或教育应用。安装方式:github,通过 npx skills add 命令从指定仓库添加。注意:涉及录音功能时需获取用户设备权限并处理隐私合规问题。

来源仓库内路径:skills/audio-producer

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/daffy0208/ai-dev-standards --skill audio-produ…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    权限没有明确标注,第一次使用时只给一个无关紧要的任务,观察它到底读了哪些文件和网络。

常见问题

6 条

audio-producer 怎么安装?

在终端执行 npx skills add https://github.com/daffy0208/ai-dev-standards --skill audio-producer。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

audio-producer 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

audio-producer 需要什么权限?

权限级别没有明确标注。第一次使用时建议只给无关紧要的任务,观察它实际读写了哪些内容。

audio-producer 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

audio-producer 用的人多吗?

公开数据是累计安装 3,374 次,近一周安装 142 次,下载 1,181 次,GitHub 26 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

audio-producer 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
frontend-design

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
audio-producer

音频制作人 · 本页

3,37426权限未标注MIT通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Audio Producer Skill

I help you build audio players, process audio, and create interactive sound experiences for the web.

What I Do

Audio Playback:

  • Custom audio players
  • Playlist management
  • Playback controls (play, pause, seek, volume)
  • Waveform visualization

Audio Processing:

  • Audio effects (reverb, delay, filters)
  • Equalization and mixing
  • Audio recording
  • Real-time audio manipulation

Interactive Audio:

  • Background music and sound effects
  • User interaction sounds
  • Spatial audio
  • Audio notifications

Custom Audio Player

// components/AudioPlayer.tsx
'use client'
import { useState, useRef, useEffect } from 'react'

interface AudioPlayerProps {
  src: string
  title?: string
  artist?: string
}

export function AudioPlayer({ src, title, artist }: AudioPlayerProps) {
  const audioRef = useRef<HTMLAudioElement>(null)
  const [playing, setPlaying] = useState(false)
  const [currentTime, setCurrentTime] = useState(0)
  const [duration, setDuration] = useState(0)
  const [volume, setVolume] = useState(1)

  useEffect(() => {
    const audio = audioRef.current
    if (!audio) return

    const updateTime = () => setCurrentTime(audio.currentTime)
    const updateDuration = () => setDuration(audio.duration)

    audio.addEventListener('timeupdate', updateTime)
    audio.addEventListener('loadedmetadata', updateDuration)
    audio.addEventListener('ended', () => setPlaying(false))

    return () => {
      audio.removeEventListener('timeupdate', updateTime)
      audio.removeEventListener('loadedmetadata', updateDuration)
      audio.removeEventListener('ended', () => setPlaying(false))
    }
  }, [])

  const togglePlay = () => {
    if (!audioRef.current) return

    if (playing) {
      audioRef.current.pause()
    } else {
      audioRef.current.play()
    }
    setPlaying(!playing)
  }

  const handleSeek = (e: React.ChangeEvent<HTMLInputElement>) => {
    const time = parseFloat(e.target.value)
    setCurrentTime(time)
    if (audioRef.current) {
      audioRef.current.currentTime = time
    }
  }

  const handleVolumeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const vol = parseFloat(e.target.value)
    setVolume(vol)
    if (audioRef.current) {
      audioRef.current.volume = vol
    }
  }

  const formatTime = (seconds: number) => {
    const mins = Math.floor(seconds / 60)
    const secs = Math.floor(seconds % 60)
    return `${mins}:${secs.toString().padStart(2, '0')}`
  }

  return (
    <div className="bg-white rounded-lg shadow-lg p-6 max-w-md">
      <audio ref={audioRef} src={src} />

      {/* Track Info */}
      {(title || artist) && (
        <div className="mb-4">
          {title && <h3 className="font-semibold text-lg">{title}</h3>}
          {artist && <p className="text-gray-600 text-sm">{artist}</p>}
        </div>
      )}

      {/* Progress Bar */}
      <div className="mb-4">
        <input
          type="range"
          min="0"
          max={duration || 0}
          value={currentTime}
          onChange={handleSeek}
          className="w-full"
        />
        <div className="flex justify-between text-sm text-gray-600 mt-1">
          <span>{formatTime(currentTime)}</span>
          <span>{formatTime(duration)}</span>
        </div>
      </div>

      {/* Controls */}
      <div className="flex items-center gap-4">
        <button
          onClick={togglePlay}
          className="w-12 h-12 bg-blue-600 text-white rounded-full flex items-center justify-center hover:bg-blue-700"
        >
          {playing ? '⏸️' : '▶️'}
        </button>

        <div className="flex items-center gap-2 flex-1">
          <span className="text-sm">🔊</span>
          <input
            type="range"
            min="0"
            max="1"
            step="0.1"
            value={volume}
            onChange={handleVolumeChange}
            className="flex-1"
          />
        </div>
      </div>
    </div>
  )
}

Podcast Player

// components/PodcastPlayer.tsx
'use client'
import { useState } from 'react'
import { AudioPlayer } from './AudioPlayer'

interface Episode {
  id: string
  title: string
  description: string
  audioUrl: string
  duration: number
  publishedAt: string
}

export function PodcastPlayer({ episodes }: { episodes: Episode[] }) {
  const [currentEpisode, setCurrentEpisode] = useState<Episode>(episodes[0])

  return (
    <div>
      <AudioPlayer
        src={currentEpisode.audioUrl}
        title={currentEpisode.title}
      />

      <div className="mt-6">
        <h3 className="font-semibold mb-4">Episodes</h3>
        <div className="space-y-2">
          {episodes.map((episode) => (
            <button
              key={episode.id}
              onClick={() => setCurrentEpisode(episode)}
              className={`w-full text-left p-4 rounded-lg ${
                currentEpisode.id === episode.id
                  ? 'bg-blue-100 border-2 border-blue-600'
                  : 'bg-gray-100'
              }`}
            >
              <h4 className="font-medium">{episode.title}</h4>
              <p className="text-sm text-gray-600 mt-1">
                {episode.description}
              </p>
              <p className="text-xs text-gray-500 mt-2">
                {new Date(episode.publishedAt).toLocaleDateString()}
              </p>
            </button>
          ))}
        </div>
      </div>
    </div>
  )
}

Waveform Visualization

// components/Waveform.tsx
'use client'
import { useEffect, useRef } from 'react'

export function Waveform({ audioSrc }: { audioSrc: string }) {
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const audioRef = useRef<HTMLAudioElement>(null)

  useEffect(() => {
    const canvas = canvasRef.current
    const audio = audioRef.current
    if (!canvas || !audio) return

    const ctx = canvas.getContext('2d')
    if (!ctx) return

    const audioContext = new AudioContext()
    const source = audioContext.createMediaElementSource(audio)
    const analyser = audioContext.createAnalyser()

    source.connect(analyser)
    analyser.connect(audioContext.destination)

    analyser.fftSize = 256
    const bufferLength = analyser.frequencyBinCount
    const dataArray = new Uint8Array(bufferLength)

    const draw = () => {
      requestAnimationFrame(draw)

      analyser.getByteFrequencyData(dataArray)

      ctx.fillStyle = 'rgb(0, 0, 0)'
      ctx.fillRect(0, 0, canvas.width, canvas.height)

      const barWidth = (canvas.width / bufferLength) * 2.5
      let x = 0

      for (let i = 0; i < bufferLength; i++) {
        const barHeight = (dataArray[i] / 255) * canvas.height

        ctx.fillStyle = `rgb(${barHeight + 100}, 50, 50)`
        ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight)

        x += barWidth + 1
      }
    }

    draw()
  }, [audioSrc])

  return (
    <div>
      <audio ref={audioRef} src={audioSrc} controls />
      <canvas ref={canvasRef} width={600} height={200} />
    </div>
  )
}

Audio Recording

// hooks/useAudioRecorder.ts
'use client'
import { useState, useRef } from 'react'

export function useAudioRecorder() {
  const [recording, setRecording] = useState(false)
  const [audioURL, setAudioURL] = useState<string | null>(null)
  const mediaRecorderRef = useRef<MediaRecorder | null>(null)
  const chunksRef = useRef<Blob[]>([])

  const startRecording = async () => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
      const mediaRecorder = new MediaRecorder(stream)

      mediaRecorder.ondataavailable = e => {
        chunksRef.current.push(e.data)
      }

      mediaRecorder.onstop = () => {
        const blob = new Blob(chunksRef.current, { type: 'audio/webm' })
        const url = URL.createObjectURL(blob)
        setAudioURL(url)
        chunksRef.current = []
      }

      mediaRecorder.start()
      mediaRecorderRef.current = mediaRecorder
      setRecording(true)
    } catch (error) {
      console.error('Failed to start recording:', error)
    }
  }

  const stopRecording = () => {
    if (mediaRecorderRef.current && recording) {
      mediaRecorderRef.current.stop()
      mediaRecorderRef.current.stream.getTracks().forEach(track => track.stop())
      setRecording(false)
    }
  }

  return { recording, audioURL, startRecording, stopRecording }
}

Usage:

'use client'
import { useAudioRecorder } from '@/hooks/useAudioRecorder'

export function VoiceRecorder() {
  const { recording, audioURL, startRecording, stopRecording } = useAudioRecorder()

  return (
    <div>
      <button
        onClick={recording ? stopRecording : startRecording}
        className={`px-6 py-3 rounded-lg ${
          recording ? 'bg-red-600' : 'bg-blue-600'
        } text-white`}
      >
        {recording ? '⏹️ Stop Recording' : '🎤 Start Recording'}
      </button>

      {audioURL && (
        <div className="mt-4">
          <audio src={audioURL} controls />
          <a
            href={audioURL}
            download="recording.webm"
            className="mt-2 inline-block px-4 py-2 bg-green-600 text-white rounded"
          >
            Download Recording
          </a>
        </div>
      )}
    </div>
  )
}

Audio Effects

// lib/audio-effects.ts

export class AudioEffects {
  private audioContext: AudioContext
  private source: MediaElementAudioSourceNode
  private gainNode: GainNode
  private filterNode: BiquadFilterNode

  constructor(audioElement: HTMLAudioElement) {
    this.audioContext = new AudioContext()
    this.source = this.audioContext.createMediaElementSource(audioElement)
    this.gainNode = this.audioContext.createGain()
    this.filterNode = this.audioContext.createBiquadFilter()

    // Connect: source -> filter -> gain -> destination
    this.source.connect(this.filterNode)
    this.filterNode.connect(this.gainNode)
    this.gainNode.connect(this.audioContext.destination)
  }

  setVolume(value: number) {
    this.gainNode.gain.value = value
  }

  setLowPassFilter(frequency: number) {
    this.filterNode.type = 'lowpass'
    this.filterNode.frequency.value = frequency
  }

  setHighPassFilter(frequency: number) {
    this.filterNode.type = 'highpass'
    this.filterNode.frequency.value = frequency
  }

  setBandPassFilter(frequency: number) {
    this.filterNode.type = 'bandpass'
    this.filterNode.frequency.value = frequency
  }
}

Spatial Audio

// components/SpatialAudio.tsx
'use client'
import { useEffect, useRef, useState } from 'react'

export function SpatialAudio({ audioSrc }: { audioSrc: string }) {
  const audioRef = useRef<HTMLAudioElement>(null)
  const [position, setPosition] = useState({ x: 0, y: 0 })

  useEffect(() => {
    const audio = audioRef.current
    if (!audio) return

    const audioContext = new AudioContext()
    const source = audioContext.createMediaElementSource(audio)
    const panner = audioContext.createPanner()

    panner.panningModel = 'HRTF'
    panner.distanceModel = 'inverse'
    panner.refDistance = 1
    panner.maxDistance = 10000

    source.connect(panner)
    panner.connect(audioContext.destination)

    // Update panner position based on mouse/touch
    panner.setPosition(position.x, position.y, 0)
  }, [position])

  return (
    <div
      onMouseMove={(e) => {
        const rect = e.currentTarget.getBoundingClientRect()
        const x = ((e.clientX - rect.left) / rect.width) * 2 - 1
        const y = ((e.clientY - rect.top) / rect.height) * 2 - 1
        setPosition({ x, y })
      }}
      className="w-full h-96 bg-gray-100 rounded-lg flex items-center justify-center cursor-crosshair"
    >
      <audio ref={audioRef} src={audioSrc} controls />
      <p className="absolute text-center text-sm text-gray-600">
        Move your mouse to change sound position
      </p>
    </div>
  )
}

When to Use Me

Perfect for:

  • Building audio players
  • Creating podcast platforms
  • Adding sound effects
  • Implementing voice recording
  • Processing audio in real-time

I'll help you:

  • Build custom audio players
  • Add waveform visualizations
  • Implement audio recording
  • Apply audio effects
  • Create spatial audio experiences

What I'll Create

🎵 Audio Players
🎙️ Voice Recorders
📊 Waveform Visualizations
🎛️ Audio Effects
🎧 Spatial Audio
🎼 Playlist Management

Let's create amazing audio experiences!

平台分布

Claude Code

28%
按下载量换算331

OpenCode

24.2%
按下载量换算286

Gemini CLI

18.07%
按下载量换算213

Codex

14.24%
按下载量换算168

Antigravity

7.66%
按下载量换算90

Cursor

3.61%
按下载量换算43

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

权限未标注

当前来源未能明确判断权限范围,默认进入异常复核队列。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

继续浏览同类 Skills