Skip to content

Update Python SDK API Reference - #112

Open
fishaudio-bot wants to merge 1 commit into
mainfrom
auto/python-api-docs
Open

Update Python SDK API Reference#112
fishaudio-bot wants to merge 1 commit into
mainfrom
auto/python-api-docs

Conversation

@fishaudio-bot

@fishaudio-bot fishaudio-bot commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Auto-generated API documentation update from fish-audio-python@448150989781e6f91c3ca9f6cc59711a87df8130

Changes

  • Updated API reference documentation for Python SDK
  • Generated from latest docstrings in the codebase

Summary by CodeRabbit

  • Documentation
    • Updated Python SDK examples, links, and error-handling guidance.
    • Added production model selection examples and clarified direct streaming and playback.
    • Documented support for model IDs and updated the default production model.
    • Added references for omission and utility streaming capabilities.
    • Reorganized SDK reference sections for easier navigation.
    • Clarified ASR duration units and updated voice state examples.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5a034557-efc3-42c5-b709-b032c788a72b

📥 Commits

Reviewing files that changed from the base of the PR and between 22780b1 and f9af9e4.

📒 Files selected for processing (5)
  • api-reference/sdk/python/core.mdx
  • api-reference/sdk/python/overview.mdx
  • api-reference/sdk/python/resources.mdx
  • api-reference/sdk/python/types.mdx
  • api-reference/sdk/python/utils.mdx
 _________________________________________________________________
< You sanitized... the wrong thing. That's impressively specific. >
 -----------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch auto/python-api-docs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api-reference/sdk/python/core.mdx`:
- Around line 1-6: Add YAML frontmatter with clear title and description before
the generated anchor in api-reference/sdk/python/core.mdx (lines 1-6) and
api-reference/sdk/python/utils.mdx (lines 1-5). Ensure both MDX pages retain
their existing anchors and comply with the required frontmatter convention.
- Around line 218-220: Update the max_message_size_bytes documentation entry so
“Default: 65536 bytes (64 KiB)” remains part of its description rather than
appearing as a separate attribute; keep the queue_size entry unchanged.

In `@api-reference/sdk/python/overview.mdx`:
- Around line 188-197: Update the async example around text_chunks to consume
client.tts.stream_websocket(...) with async iteration instead of awaiting it
before play(audio_stream). Align the example with the documented async iterator
pattern and preserve the existing streaming behavior.

In `@api-reference/sdk/python/resources.mdx`:
- Around line 285-388: Update the async stream_websocket documentation examples
to consume AsyncTTSClient.stream_websocket with async for, writing or processing
each yielded audio chunk directly. Replace any await-assigned stream usage and
play(audio_stream) pattern in overview.mdx while preserving the existing
examples’ behavior and parameters.

In `@api-reference/sdk/python/utils.mdx`:
- Around line 30-37: Add an explicit mpv installation or PATH prerequisite
between the Raises and Examples sections in the stream documentation, so users
know to make mpv available before running the stream example. Preserve the
existing example and DependencyError documentation.
- Around line 37-49: Dedent the fenced Python examples in the Examples sections,
including the blocks containing FishAudio stream usage, so each opening and
closing fence starts at column 0 and the Python body is aligned without the
extra four-space indentation. Apply the same formatting to all referenced
examples while preserving their code and python language tags.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5a034557-efc3-42c5-b709-b032c788a72b

📥 Commits

Reviewing files that changed from the base of the PR and between 22780b1 and f9af9e4.

📒 Files selected for processing (5)
  • api-reference/sdk/python/core.mdx
  • api-reference/sdk/python/overview.mdx
  • api-reference/sdk/python/resources.mdx
  • api-reference/sdk/python/types.mdx
  • api-reference/sdk/python/utils.mdx

Comment on lines +1 to +6
<a id="fishaudio.core.omit"></a>

# fishaudio.core.omit

OMIT sentinel for distinguishing None from not-provided parameters.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add required frontmatter to both API-reference pages.

Both pages begin with generated anchors. Neither page declares the required YAML title and description.

  • api-reference/sdk/python/core.mdx#L1-L6: Add frontmatter before <a id="fishaudio.core.omit"></a>.
  • api-reference/sdk/python/utils.mdx#L1-L5: Add frontmatter before <a id="fishaudio.utils.stream"></a>.

As per coding guidelines, do not skip frontmatter on any MDX file. Include a clear title and description in the YAML frontmatter.

📍 Affects 2 files
  • api-reference/sdk/python/core.mdx#L1-L6 (this comment)
  • api-reference/sdk/python/utils.mdx#L1-L5
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api-reference/sdk/python/core.mdx` around lines 1 - 6, Add YAML frontmatter
with clear title and description before the generated anchor in
api-reference/sdk/python/core.mdx (lines 1-6) and
api-reference/sdk/python/utils.mdx (lines 1-5). Ensure both MDX pages retain
their existing anchors and comply with the required frontmatter convention.

Source: Coding guidelines

Comment on lines +218 to +220
- `max_message_size_bytes` - Message size in bytes to receive from the server.
- `Default` - 65536 bytes (64 KiB).
- `queue_size` - Size of the queue where received messages will be held until they

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the default value under max_message_size_bytes.

Line 219 is rendered as a separate attribute named Default. Move the value into the max_message_size_bytes description.

Proposed fix
-- `max_message_size_bytes` - Message size in bytes to receive from the server.
-- `Default` - 65536 bytes (64 KiB).
+- `max_message_size_bytes` - Message size in bytes to receive from the server.
+  Default: 65536 bytes (64 KiB).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `max_message_size_bytes` - Message size in bytes to receive from the server.
- `Default` - 65536 bytes (64 KiB).
- `queue_size` - Size of the queue where received messages will be held until they
- `max_message_size_bytes` - Message size in bytes to receive from the server.
Default: 65536 bytes (64 KiB).
- `queue_size` - Size of the queue where received messages will be held until they
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api-reference/sdk/python/core.mdx` around lines 218 - 220, Update the
max_message_size_bytes documentation entry so “Default: 65536 bytes (64 KiB)”
remains part of its description rather than appearing as a separate attribute;
keep the queue_size entry unchanged.

Comment on lines 188 to +197
async def text_chunks():
yield "Hello, "
yield "this is "
yield "streaming!"

async def main():
async with AsyncFishAudio() as client:
# stream_websocket is an async generator — iterate it, don't await the call
audio_stream = client.tts.stream_websocket(text_chunks(), latency="balanced")
with open("out.mp3", "wb") as f:
async for chunk in audio_stream:
f.write(chunk)

asyncio.run(main())
audio_stream = await client.tts.stream_websocket(text_chunks(), latency="balanced")
play(audio_stream)
```

[Learn more](https://docs.fish.audio/features/realtime-streaming)
[Learn more](https://docs.fish.audio/developer-guide/sdk-guide/python/websocket)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
git ls-files | rg '(^|/)api-reference/sdk/python/(overview|resources)\.mdx$|(^|/)src/|^packages/|pyproject\.toml|README' || true

echo
echo "== overview snippet =="
sed -n '170,210p' api-reference/sdk/python/overview.mdx

echo
echo "== resources around method docs =="
sed -n '540,590p' api-reference/sdk/python/resources.mdx

echo
echo "== search stream_websocket occurrences =="
rg -n "stream_websocket|AsyncTTSClient|tts\.stream_websocket|for .* stream_websocket|await .* stream_websocket" api-reference/sdk/python . --glob '!**/.git/**' | head -200

Repository: fishaudio/docs

Length of output: 12956


🌐 Web query:

Fish.audio SDK Python AsyncTTSClient stream_websocket example async for await documentation

💡 Result:

To perform real-time, token-by-token text-to-speech streaming with the Fish.audio Python SDK using AsyncTTSClient (accessed via AsyncFishAudio), you should use the stream_websocket method [1][2]. The stream_websocket method is an asynchronous generator [1][3]. You do not await the call itself; instead, you iterate over it using an async for loop [1][2]. This allows you to process or play back each audio chunk as soon as it is received from the server [1][4]. Example usage: import asyncio from fishaudio import AsyncFishAudio async def text_chunks: # This async generator yields text tokens as they become available yield "Hello, " yield "this is " yield "streaming via WebSocket!" async def main: async with AsyncFishAudio as client: # stream_websocket is an async generator — iterate it, don't await the call audio_stream = client.tts.stream_websocket( text_chunks, reference_id="YOUR_VOICE_ID", latency="balanced") async for chunk in audio_stream: # Handle the incoming audio chunk (e.g., write to file or stream to audio device) print(f"Received {len(chunk)} bytes of audio") # with open("out.mp3", "ab") as f: # f.write(chunk) asyncio.run(main) Key implementation details: 1. Input Generator: You must provide an iterable (or async iterable) that yields text tokens [1][4]. 2. Streaming Iteration: Use async for chunk in client.tts.stream_websocket(...) to consume the audio chunks [4][2]. 3. Lifecycle: The SDK handles the underlying WebSocket lifecycle (frames, connection, etc.) automatically [1][4]. 4. Async Clients: Ensure you are using AsyncFishAudio for asynchronous operations, as FishAudio is for synchronous usage [1][5]. For further details, refer to the official Fish Audio documentation on WebSocket streaming [1] and the SDK cookbook [4].

Citations:


🌐 Web query:

site:docs.fish.audio/developer-guide/sdk-guide/python/websocket "async for chunk" "stream_websocket"

💡 Result:

The async for loop is the standard pattern in Python for consuming asynchronous streams, such as those provided by WebSocket clients [1]. When working with WebSocket APIs that support streaming (like text-to-speech or real-time data feeds), the client typically provides an asynchronous generator that yields chunks as they arrive over the network [1]. To use this pattern, you define an asynchronous loop that iterates over the response stream. This allows your application to process or forward each chunk immediately without waiting for the entire stream to complete [1]. Example Implementation: The following example demonstrates how to consume a stream from an asynchronous WebSocket client [1]: async def main: client = AsyncFishAudio # Define an async generator to provide input tokens/data async def data_source: async for item in your_async_source: yield item # Use async for to iterate over the WebSocket stream as chunks arrive async for chunk in client.tts.stream_websocket(data_source): # Process each chunk as it arrives process(chunk) asyncio.run(main) Key implementation details: - Async Generator: The method (e.g., stream_websocket) is designed as an asynchronous generator [1]. - Non-blocking: By using async for, your program remains responsive, allowing other tasks to run while waiting for new chunks to arrive from the WebSocket connection [1]. - Protocol Handling: While high-level SDKs often handle framing (such as MessagePack or JSON) automatically, direct WebSocket implementations require manual management of message framing and connection state if not using a library-provided method [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== websocket docs =="
for f in api-reference/sdk/python/overview.mdx developer-guide/sdk-guide/python/websocket.mdx; do
  if [ -f "$f" ]; then
    echo "-- $f --"
    sed -n '1,240p' "$f"
  fi
done

echo
echo "== realtime streaming docs sync/async snippets =="
sed -n '180,210p' features/realtime-streaming.mdx || true
sed -n '50,75p' developer-guide/best-practices/real-time-streaming.mdx || true
sed -n '135,155p' developer-guide/best-practices/real-time-streaming.mdx || true

Repository: fishaudio/docs

Length of output: 8648


Use async iteration for stream_websocket in the async example.

features/realtime-streaming.mdx states that async clients expose the same streaming methods and explicitly shows async for chunk in client.tts.stream_websocket(...). resources.mdx also documents the same method as an async iterator, so api-reference/sdk/python/overview.mdx should not await client.tts.stream_websocket(...) before play(audio_stream); align it with the async async for pattern shown elsewhere.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api-reference/sdk/python/overview.mdx` around lines 188 - 197, Update the
async example around text_chunks to consume client.tts.stream_websocket(...)
with async iteration instead of awaiting it before play(audio_stream). Align the
example with the documented async iterator pattern and preserve the existing
streaming behavior.

Comment on lines +285 to +388
<a id="fishaudio.resources.tts.TTSClient.stream_websocket"></a>

#### stream\_websocket

```python
async def create(*,
title: str,
voices: builtins.list[bytes],
description: Optional[str] = OMIT,
texts: Optional[builtins.list[str]] = OMIT,
tags: Optional[builtins.list[str]] = OMIT,
cover_image: Optional[bytes] = OMIT,
visibility: Visibility = "private",
train_mode: str = "fast",
enhance_audio_quality: bool = True,
request_options: Optional[RequestOptions] = None) -> Voice
def stream_websocket(
text_stream: Iterable[Union[str, TextEvent, FlushEvent]],
*,
reference_id: Optional[str] = None,
references: Optional[list[ReferenceAudio]] = None,
format: Optional[AudioFormat] = None,
latency: Optional[LatencyMode] = None,
speed: Optional[float] = None,
config: TTSConfig = TTSConfig(),
model: Union[Model, str] = "s2.1-pro",
max_workers: int = 10,
ws_options: Optional[WebSocketOptions] = None) -> Iterator[bytes]
```

Create/clone a new voice (async). See sync version for details.
Stream text and receive audio in real-time via WebSocket.

<a id="fishaudio.resources.voices.AsyncVoicesClient.update"></a>
Perfect for conversational AI, live captioning, and streaming applications.

#### update
**Arguments**:

- `text_stream` - Iterator of text chunks to stream
- `reference_id` - Voice reference ID (overrides config.reference_id if provided)
- `references` - Reference audio samples (overrides config.references if provided)
- `format` - Audio format - "mp3", "wav", "pcm", or "opus" (overrides config.format if provided)
- `latency` - Latency mode - "normal" or "balanced" (overrides config.latency if provided)
- `speed` - Speech speed multiplier, e.g. 1.5 for 1.5x speed (overrides config.prosody.speed if provided)
- `config` - TTS configuration (audio settings, voice, model parameters)
- `model` - TTS model to use
- `max_workers` - ThreadPoolExecutor workers for concurrent sender
- `ws_options` - WebSocket connection options for configuring timeouts, message size limits, etc.
Useful for long-running generations that may exceed default timeout values.
See WebSocketOptions class for available parameters.


**Returns**:

Iterator of audio bytes


**Example**:

```python
from fishaudio import FishAudio, TTSConfig, ReferenceAudio, WebSocketOptions

client = FishAudio(api_key="...")

def text_generator():
yield "Hello, "
yield "this is "
yield "streaming text!"

# Simple usage with defaults
with open("output.mp3", "wb") as f:
for audio_chunk in client.tts.stream_websocket(text_generator()):
f.write(audio_chunk)

# With format and speed parameters
with open("output.wav", "wb") as f:
for audio_chunk in client.tts.stream_websocket(
text_generator(),
format="wav",
speed=1.3
):
f.write(audio_chunk)

# With reference_id parameter
with open("output.mp3", "wb") as f:
for audio_chunk in client.tts.stream_websocket(text_generator(), reference_id="your_model_id"):
f.write(audio_chunk)

# With references parameter
with open("output.mp3", "wb") as f:
for audio_chunk in client.tts.stream_websocket(
text_generator(),
references=[ReferenceAudio(audio=audio_bytes, text="sample")]
):
f.write(audio_chunk)

# With WebSocket options for long-running generations
# Useful if you're generating very long responses that may take >20 seconds
ws_options = WebSocketOptions(keepalive_ping_timeout_seconds=60.0)
with open("output.mp3", "wb") as f:
for audio_chunk in client.tts.stream_websocket(
text_generator(),
ws_options=ws_options
):
f.write(audio_chunk)

# Parameters override config values
config = TTSConfig(format="mp3", latency="balanced")
with open("output.wav", "wb") as f:
for audio_chunk in client.tts.stream_websocket(
text_generator(),
format="wav", # Parameter wins
config=config
):
f.write(audio_chunk)
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
fd -a 'resources\.mdx|overview\.mdx' . | sed 's#^\./##'

echo
echo "== resources.mdx stream_websocket sections =="
file="api-reference/sdk/python/resources.mdx"
if [ -f "$file" ]; then
  wc -l "$file"
  sed -n '280,395p' "$file"
  sed -n '500,620p' "$file"
fi

echo
echo "== overview.mdx stream_websocket/async usage =="
overview="api-reference/sdk/python/overview.mdx"
if [ -f "$overview" ]; then
  rg -n "stream_websocket|async for|await client\.tts|play\\(" "$overview" -C 4
fi

echo
echo "== repo source references to AsyncTTSClient.stream_websocket =="
rg -n "class AsyncTTSClient|async def stream_websocket|def stream_websocket|AsyncTTSClient|stream_websocket" . -g '!**/build/**' -g '!**/dist/**' -g '!**/node_modules/**' | head -200

Repository: fishaudio/docs

Length of output: 17427


Align the async stream_websocket examples to async iteration.

AsyncTTSClient.stream_websocket is documented as an async generator, so use async for chunk in client.tts.stream_websocket(...) and avoid audio_stream = await client.tts.stream_websocket(...) followed by play(audio_stream) in overview.mdx.

🧰 Tools
🪛 GitHub Check: Mintlify Validation (hanabiaiinc) - vale-spellcheck

[warning] 290-290: api-reference/sdk/python/resources.mdx#L290
Did you really mean 'stream_websocket'?


[warning] 313-313: api-reference/sdk/python/resources.mdx#L313
Did you really mean 'wav'?


[warning] 313-313: api-reference/sdk/python/resources.mdx#L313
Did you really mean 'pcm'?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api-reference/sdk/python/resources.mdx` around lines 285 - 388, Update the
async stream_websocket documentation examples to consume
AsyncTTSClient.stream_websocket with async for, writing or processing each
yielded audio chunk directly. Replace any await-assigned stream usage and
play(audio_stream) pattern in overview.mdx while preserving the existing
examples’ behavior and parameters.

Comment on lines +30 to +37
**Raises**:

- `DependencyError` - If mpv is not installed


**Examples**:

```python

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files | rg '(^|/)utils\.mdx$|\.mdx$' || true

echo
echo "Target file outline (if possible):"
ast-grep outline api-reference/sdk/python/utils.mdx || true

echo
echo "Target file lines 1-120:"
cat -n api-reference/sdk/python/utils.mdx | sed -n '1,120p'

echo
echo "Search for stream function / DependencyError examples:"
rg -n "def stream|stream\(|DependencyError|mpv" api-reference/sdk/python/utils.mdx api-reference -S || true

Repository: fishaudio/docs

Length of output: 10927


Add an mpv prerequisite before the stream example.

stream() plays audio with mpv, and DependencyError is raised when mpv is not installed. Add the prerequisite before Examples so users can install mpv or make it available on PATH before running the code.

🧰 Tools
🪛 GitHub Check: Mintlify Validation (hanabiaiinc) - vale-spellcheck

[warning] 32-32: api-reference/sdk/python/utils.mdx#L32
Did you really mean 'mpv'?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api-reference/sdk/python/utils.mdx` around lines 30 - 37, Add an explicit mpv
installation or PATH prerequisite between the Raises and Examples sections in
the stream documentation, so users know to make mpv available before running the
stream example. Preserve the existing example and DependencyError documentation.

Source: Coding guidelines

Comment on lines +37 to +49
```python
from fishaudio import FishAudio, stream

client = FishAudio(api_key="...")
audio_stream = client.tts.convert(text="Hello world")

# Stream and play in real-time, get complete audio
complete_audio = stream(audio_stream)

# Save the captured audio
with open("output.mp3", "wb") as f:
f.write(complete_audio)
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

awk '
/^[[:space:]]*```python$/ || /^[[:space:]]*```$/ {
  if ($0 !~ /^```python$/ && $0 !~ /^```$/) {
    print "Indented fenced block at Line " NR
    bad = 1
  }
}
END { exit bad }
' api-reference/sdk/python/utils.mdx

Repository: fishaudio/docs

Length of output: 352


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf 'Context for api-reference/sdk/python/utils.mdx lines 1-170:\n'
nl -ba api-reference/sdk/python/utils.mdx | sed -n '1,170p'

printf '\nMarkdown fence indentation evidence:\n'
python3 - <<'PY'
from pathlib import Path
p = Path("api-reference/sdk/python/utils.mdx")
for n, line in enumerate(p.read_text().splitlines(), 1):
    stripped = line.strip()
    if stripped.startswith("```"):
        print(f"{n}: leading_spaces={len(line)-len(line.lstrip())!r} line={line!r}")
PY

Repository: fishaudio/docs

Length of output: 252


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf 'Context for api-reference/sdk/python/utils.mdx lines 1-170:\n'
awk '{printf "%5d\t%s\n", NR, $0}' api-reference/sdk/python/utils.mdx | sed -n '1,170p'

printf '\nMarkdown fence indentation evidence:\n'
python3 - <<'PY'
from pathlib import Path
p = Path("api-reference/sdk/python/utils.mdx")
for n, line in enumerate(p.read_text().splitlines(), 1):
    stripped = line.strip()
    if stripped.startswith("```"):
        print(f"{n}: leading_spaces={len(line)-len(line.lstrip())!r} line={line!r}")
PY

printf '\nMarkdown fence counts:\n'
python3 - <<'PY'
from pathlib import Path
p = Path("api-reference/sdk/python/utils.mdx")
fences = [line for line in p.read_text().splitlines() if line.strip().startswith("```")]
print("fence_count:", len(fences))
print("indented_fence_count:", [line for line in fences if line.startswith("    ```")])
PY

Repository: fishaudio/docs

Length of output: 4292


Dedent the fenced Python examples.

api-reference/sdk/python/utils.mdx has fenced examples under **Examples** at lines 37–49, 84–98, and 124–136 that are indented by four spaces. Some Markdown/MDX parsers treat these as indented code blocks instead of language-tagged fenced blocks. Place the fences at column 0 and dedent the python bodies so the language tags render consistently.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api-reference/sdk/python/utils.mdx` around lines 37 - 49, Dedent the fenced
Python examples in the Examples sections, including the blocks containing
FishAudio stream usage, so each opening and closing fence starts at column 0 and
the Python body is aligned without the extra four-space indentation. Apply the
same formatting to all referenced examples while preserving their code and
python language tags.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant