Install
openclaw skills install fish-ttsGenerate high-quality speech from text using Fish Audio S1 and optionally upload the MP3 audio file to NextCloud via WebDAV.
openclaw skills install fish-ttsThis skill uses Fish Audio S1 to generate high-quality text-to-speech audio and upload it to NextCloud.
http://localhost:7860Generate speech from text:
curl -s -X POST http://192.168.68.78:7860/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"fish", "text":"Hello from Fish Audio S1!", "voice":"em_michael"}' \
-o /tmp/fish_audio.mp3
Upload to NextCloud:
curl -s -u "$NEXTCLOUD_USER:$NEXTCLOUD_PASS" \
-X PUT -T /tmp/fish_audio.mp3 \
"http://192.168.68.68:8080/remote.php/webdav/Openclaw/fish_audio.mp3"
Set these environment variables if not already set:
export NEXTCLOUD_USER="openclaw"
export NEXTCLOUD_PASS="N95qg-Wzdpc-6DJAn-xMaHa-RaEW5"
export NEXTCLOUD_URL="http://192.168.68.68:8080"
export FISH_AUDIO_S1_URL="http://192.168.68.78:7860"
Fish Audio S1 provides many high-quality voices. Common options:
em_michael - Authoritative, businessem_pierre - French, professionalem_marcus - German, confidentaf_bella - Warm, naturalaf_nicole - Clear, articulateaf_rachel - Friendly, conversationalem_alex - Expressive male (warm tone, wide range)af_sarah - Friendly, youthfulem_pierreem_marcusaf_alice, af_emma[happy], [sad], [excited]Hello! [happy] I am so happy to meet you today.POST http://192.168.68.78:7860/v1/audio/speech
Request Format:
{
"model": "fish",
"text": "Your text here",
"voice": "Voice name from list above",
"output": "output file path or 'upload to NextCloud'"
}
PUT http://192.168.68.68:8080/remote.php/webdav/Openclaw/path/to/file.mp3
Headers:
Authorization: Basic <base64_credentials>Content-Type: audio/mpeg/Openclaw/ or custom subfolderNEXTCLOUD_USER:NEXTCLOUD_PASS# Check if service is running
curl -s http://192.168.68.78:7860/health
# Check if can generate audio
curl -s -X POST http://192.168.68.78:7860/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"fish", "text":"test", "voice":"em_alex"}' \
-o /tmp/test.mp3
# Test NextCloud connectivity
curl -s -I "http://192.168.68.68:8080" \
-u "$NEXTCLOUD_USER:$NEXTCLOUD_PASS"
-X PROPFIND -H "Depth:0" \
"http://192.168.68.68:8080/remote.php/webdav/Openclaw/"
If Fish Audio S1 is not available, try:
curl -s -X POST http://192.168.68.78:7860/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"fish", "text":"Hello! How are you today?", "voice":"em_michael"}' \
-o /tmp/greeting.mp3
curl -s -X POST http://192.168.68.78:7860/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"fish", "text":"I am so excited to tell you about this amazing opportunity! [excited]", "voice":"af_sarah"}' \
-o /tmp/excited.mp3
# Generate audio
curl -s -X POST http://192.168.68.78:7860/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"fish", "text":"This is a test file for NextCloud upload.", "voice":"em_michael"}' \
-o /tmp/test_file.mp3
# Upload to NextCloud
curl -s -u "$NEXTCLOUD_USER:$NEXTCLOUD_PASS" \
-X PUT -T /tmp/test_file.mp3 \
"http://192.168.68.68:8080/remote.php/webdav/Openclaw/test_file.mp3"
Complete list of available Fish Audio S1 voices (for testing):
2026/02/09/ for daily uploadsgreeting_em_michael_20260209.mp3)#!/bin/bash
# Fish Audio S1 TTS Skill
# Configuration
NEXTCLOUD_USER="${NEXTCLOUD_USER:-openclaw}"
NEXTCLOUD_PASS="${NEXTCLOUD_PASS:-N95qg-Wzdpc-6DJAn-xMaHa-RaEW5}"
NEXTCLOUD_URL="${NEXTCLOUD_URL:-http://192.168.68.68:8080}"
FISH_AUDIO_S1_URL="${FISH_AUDIO_S1_URL:-http://192.168.68.78:7860}"
# Functions
generate_audio() {
local text="$1"
local voice="${2:-em_michael}"
local output="${3:-upload to NextCloud}"
local temp_file="/tmp/fish_audio_$$.mp3"
# Generate audio
if ! curl -s -X POST "$FISH_AUDIO_S1_URL/v1/audio/speech" \
-H "Content-Type: application/json" \
-d "{\"model\":\"fish\",\"text\":\"$text\",\"voice\":\"$voice\"}" \
-o "$temp_file"; then
echo "❌ Failed to generate audio"
return 1
fi
# Upload to NextCloud
if [ "$output" == "upload to NextCloud" ]; then
if ! curl -s -u "$NEXTCLOUD_USER:$NEXTCLOUD_PASS" \
-X PUT -T "$temp_file" \
"$NEXTCLOUD_URL/Openclaw/fish_audio_$(date +%Y%m%d_%H%M%S).mp3"; then
echo "❌ Failed to upload to NextCloud"
return 1
fi
fi
# Return audio file if just generating
if [ "$output" != "upload to NextCloud" ]; then
echo "$temp_file"
fi
return 0
}
main() {
# Parse command line arguments
local action="$1"
local text="$2"
local voice="${3:-em_michael}"
local output="${4:-upload to NextCloud}"
case "$action" in
generate)
generate_audio "$text" "$voice" "$output"
;;
upload)
echo "Upload functionality requires generated audio file"
return 1
;;
help)
echo "Usage: $0 [generate|upload] [text] [voice]"
echo ""
echo "Commands:"
echo " generate - Generate audio from text and upload to NextCloud"
echo " upload - Upload existing MP3 file to NextCloud"
echo ""
echo "Options:"
echo " [voice] - Voice name (default: em_michael)"
echo " [output] - Output destination (default: upload to NextCloud)"
echo ""
echo "Examples:"
echo " $0 generate Hello! I am excited to meet you."
echo " $0 generate [happy] This is great news! [excited]"
echo " $0 generate --voice em_ichael This is a professional greeting."
echo " $0 upload /path/to/file.mp3 Upload file to NextCloud"
;;
*)
echo "Unknown action: $action"
return 1
;;
esac
}
# Run main function
main "$@"
MIT License - Free to use, modify, and distribute
For issues or questions:
curl -s -X POST http://192.168.68.78:7860/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"fish", "text":"Hello! This is a test of the Fish Audio S1 TTS skill for OpenClaw.", "voice":"em_michael"}' \
-o /tmp/fish_audio_test.mp3
curl -s -u "$NEXTCLOUD_USER:$NEXTCLOUD_PASS" \
-X PUT -T /tmp/fish_audio_test.mp3 \
"http://192.168.68.68:8080/remote.php/webdav/Openclaw/fish_audio_test.mp3"
This skill provides: