技能备份 - 2026-04-15 (40个技能)

This commit is contained in:
root
2026-04-15 18:53:15 +08:00
parent f62f14814f
commit c65fce24e4
791 changed files with 190773 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash
# Generate ogg/opus voice file from text using edge-tts + ffmpeg
# Usage: gen_voice.sh <text> <output.ogg> [voice]
# Default voice: zh-CN-XiaoxiaoNeural
set -e
TEXT="$1"
OUTPUT="$2"
VOICE="${3:-zh-CN-XiaoxiaoNeural}"
if [ -z "$TEXT" ] || [ -z "$OUTPUT" ]; then
echo "Usage: gen_voice.sh <text> <output.ogg> [voice]"
exit 1
fi
TMP_MP3=$(mktemp /tmp/voice_XXXXXX.mp3)
trap "rm -f $TMP_MP3" EXIT
edge-tts --voice "$VOICE" --text "$TEXT" --write-media "$TMP_MP3" 2>&1
ffmpeg -y -i "$TMP_MP3" -c:a libopus -b:a 64k "$OUTPUT" 2>&1 | tail -1
echo "Generated: $OUTPUT"
@@ -0,0 +1,65 @@
#!/usr/bin/env python3
"""Generate Discord voice message waveform from an ogg file.
Usage: gen_waveform.py <ogg_file>
Output: JSON with duration_secs and base64-encoded waveform (256 points, 0-255).
"""
import subprocess
import struct
import base64
import json
import sys
def main():
if len(sys.argv) < 2:
print("Usage: gen_waveform.py <ogg_file>")
sys.exit(1)
ogg_file = sys.argv[1]
# Get duration
result = subprocess.run(
["ffprobe", "-v", "error", "-show_entries", "format=duration",
"-of", "csv=p=0", ogg_file],
capture_output=True, text=True
)
duration_secs = float(result.stdout.strip())
# Extract raw PCM (mono, 16-bit, 48kHz)
result = subprocess.run(
["ffmpeg", "-i", ogg_file, "-f", "s16le", "-ac", "1",
"-ar", "48000", "-"],
capture_output=True
)
pcm_data = result.stdout
# Parse samples
num_samples = len(pcm_data) // 2
samples = struct.unpack(f"<{num_samples}h", pcm_data[:num_samples * 2])
# Generate 256-point waveform
points = 256
chunk_size = max(1, num_samples // points)
waveform = []
for i in range(points):
start = i * chunk_size
end = min(start + chunk_size, num_samples)
if start >= num_samples:
waveform.append(0)
continue
chunk = samples[start:end]
avg = sum(abs(s) for s in chunk) / len(chunk)
# Map to 0-255
val = min(255, int(avg / 32768 * 255))
waveform.append(val)
waveform_b64 = base64.b64encode(bytes(waveform)).decode()
print(json.dumps({
"duration_secs": round(duration_secs, 2),
"waveform": waveform_b64
}))
if __name__ == "__main__":
main()
@@ -0,0 +1,46 @@
#!/bin/bash
# Send voice message to Feishu/Lark
# Usage: send_feishu_voice.sh <ogg_file> <receive_id> <tenant_access_token> [receive_id_type]
# receive_id_type: open_id (default), chat_id, user_id, union_id, email
set -e
OGG_FILE="$1"
RECEIVE_ID="$2"
TOKEN="$3"
ID_TYPE="${4:-open_id}"
API_BASE="https://open.feishu.cn/open-apis"
if [ -z "$OGG_FILE" ] || [ -z "$RECEIVE_ID" ] || [ -z "$TOKEN" ]; then
echo "Usage: send_feishu_voice.sh <ogg_file> <receive_id> <token> [receive_id_type]"
exit 1
fi
# 1. Get duration in milliseconds
DURATION_SEC=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$OGG_FILE")
DURATION_MS=$(python3 -c "print(int(float('$DURATION_SEC') * 1000))")
# 2. Upload file to Feishu
UPLOAD_RESP=$(curl -s -X POST "$API_BASE/im/v1/files" \
-H "Authorization: Bearer $TOKEN" \
-F "file_type=opus" \
-F "file_name=voice.ogg" \
-F "duration=$DURATION_MS" \
-F "file=@$OGG_FILE")
FILE_KEY=$(echo "$UPLOAD_RESP" | python3 -c "import json,sys; print(json.load(sys.stdin).get('data',{}).get('file_key',''))")
if [ -z "$FILE_KEY" ]; then
echo "Upload failed: $UPLOAD_RESP"
exit 1
fi
echo "Uploaded: file_key=$FILE_KEY"
# 3. Send audio message
SEND_RESP=$(curl -s -X POST "$API_BASE/im/v1/messages?receive_id_type=$ID_TYPE" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"receive_id\":\"$RECEIVE_ID\",\"msg_type\":\"audio\",\"content\":\"{\\\"file_key\\\":\\\"$FILE_KEY\\\"}\"}")
echo "Send result: $SEND_RESP"