Skip to content

Fish Speech Drama 3 Parity Roadmap #1188

Closed

Description

@DarkTyger

fish_drama3: changes needed for parity with Fish Speech's Drama 3

An analysis from Claude Code on max setting before an attempt was made to integrate audio.cpp with FS Drama 3. Feel free to close as won't fix.

We narrate audiobooks with fishaudio/drama-3 through Fish Speech 1ff3c3e. It runs on an NVIDIA T1000 (Turing, sm_75, 8 GB) with the routed experts in host RAM, and we'd like to move it to fish_drama3. We compared the port on main (as of 2026-11-03) with Fish Speech. This issue identifies possible updates necessary to run on that card. #1 needs a package or a confirmed conversion. A client can work around #2–#6, by setting the session option itself or by sending one chunk per request with its own previous_takes. Even so, the port's defaults and built-in long-form path still differ from Fish Speech's generate_long_drama3.

1. No package with 8-bit experts

  • The release ships "FP8 MoE experts with the remaining weights in bf16". We dequantize the experts to BF16, so we run them at essentially the release's precision.
  • Jmica/Drama-3-GGUF only has Q4_K, Q3_K and Q2_K expert banks.
  • The model doc's known issues say emotion and nonverbal prompts can "produce prolonged reactions, omit dialogue or reach the generation cap", and that "This occurs with both the original Q4-expert package and smaller formats." Our quotations carry such directions, so we'd want quantization ruled out as the cause.
  • convert_fish_drama3.py takes --expert-type, but the doc only shows q3_k and q4_k.
  • Ask: confirm that --expert-type q8_0 works, and ideally publish a Q8_0-expert package.

2. BF16 reference encoding is on by default on Turing

  • Turing has no native BF16 arithmetic. The doc says: "On CUDA, BF16 reference-encoder arithmetic is enabled by default with F16/BF16 codec weights." It reports testing on an RTX PRO 6000 Blackwell.
  • Ask: default fish_drama3.codec_encoder_bf16_compute to false below compute capability 8.0, or confirm it's safe there.

3. History doesn't keep the first chunk

  • Fish Speech's Drama3History (chunking.py) keeps a request's first chunk in every later chunk's history and adds the most recent one (DRAMA3_HISTORY_RECENT_TURNS = 1).
  • The port adds only the previous chunk (session.cpp):
    if (!generated_takes.empty()) context.push_back(generated_takes.back());
  • Ask: keep the first generated chunk as well.

4. Prompts that outgrow the context are rejected

  • When build_drama3_prompt raises Drama3PromptTooLongError, Fish Speech (inference.py) tries shorter histories, longest first. It also caps each chunk's new tokens at the room left: limit = capacity - len(prompt), budget = min(requested, limit).
  • The port throws before decoding (generator.cpp): "Drama 3 prompt plus max_tokens exceeds fish_drama3.context_length; increase it or shorten history." fish_drama3.context_length defaults to 2048 and max_tokens to 1024.
  • Ask: clamp max_tokens to the context left, and fall back to shorter histories as Fish Speech does.

5. A chunk that ends before its first frame

  • Fish Speech logs "The model emitted EOS before any audio frame", yields nothing for that chunk, leaves it out of the history, and goes on.
  • The port throws Drama 3 ended before producing an audio frame (generator.cpp).
  • Ask: skip the chunk the same way, and report the skip in drama3_generation_v1.

6. Chunk size and per-chunk token cap

  • Fish Speech splits at DRAMA3_CHUNK_BYTES = 300 UTF-8 bytes. That is a threshold, not a hard cap: a protected span such as a <|…|> token or a [bracketed] cue stays whole even when it is longer. Each chunk may add DRAMA3_CHUNK_MAX_NEW_TOKENS = 600 new tokens, about 27.9 s.
  • The port defaults to text_chunk_size=128 characters and max_tokens=1024.
  • Ask: default to Fish Speech's 300-byte budget and 600-token cap.

Activity

  1. 0xShug0 commented on Nov 3, 2026

    @0xShug0
    Owner

    @DarkTyger Thanks for the suggestions!. 5/6 should not become default behavior as proposed. #891 has more measurements and context. And 5 turns an explicit failure into silence missing narration. For 5, we could add an opt-in option, similar to Higgs Audio, to skip empty chunks and continue generation. The default should still report an error so missing speech isn’t silently accepted.

    For 2, the option is not merely a hardware-compatibility toggle. It can change output and performance.

    I will look at 3 and 4.

  2. 0xShug0 commented on Nov 4, 2026

    @0xShug0
    Owner

    @DarkTyger 3 and 4 are fixed. Could you share a test case to reproduce 5?

  3. DarkTyger commented on Nov 4, 2026

    @DarkTyger
    Author

    issue-5.md

    Claude generated so hopefully it works. To use it, make an empty directory, paste the script in as issue-5.sh, chmod +x it and run it.

  4. 0xShug0 commented on Nov 4, 2026

    @0xShug0
    Owner

    @DarkTyger Thanks! Reproduced the issue and added an opt-in skip_empty_chunks option to log a warning and skip empty chunks, matching upstream. The default still throws so downstream app can catch and handle the failure.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions