Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public static Command Create()
command.Subcommands.Add(OpenAPIV1CreateAsrCommandApiCommand.Create());
command.Subcommands.Add(OpenAPIV1CreateTtsCommandApiCommand.Create());
command.Subcommands.Add(OpenAPIV1CreateTtsStreamWithTimestampCommandApiCommand.Create());
command.Subcommands.Add(OpenAPIV1CreateVoiceDesignCommandApiCommand.Create());
return command;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
#nullable enable
#pragma warning disable CS0618

using System.CommandLine;

namespace FishAudio.CLI.Commands;

internal static partial class OpenAPIV1CreateVoiceDesignCommandApiCommand
{
private static Option<string> Model { get; } = new(
name: @"--model")
{
Description = @"Specify which voice-design model to use.",
DefaultValueFactory = _ => "voice-design-1",
};

private static Option<string> Instruction { get; } = new(
name: @"--instruction")
{
Description = @"Voice design prompt. Must contain 1 to 2000 characters.",
Required = true,
};

private static Option<string?> ReferenceText { get; } = new(
name: @"--reference-text")
{
Description = @"Optional text used as reference content for the generated voice.",
};

private static Option<string?> Language { get; } = new(
name: @"--language")
{
Description = @"Optional BCP-47 language hint, such as `en`, `zh`, or `ja`.",
};

private static Option<int?> N { get; } = new(
name: @"--n")
{
Description = @"Number of voice candidates to generate.",
};

private static Option<double?> Speed { get; } = new(
name: @"--speed")
{
Description = @"Speaking speed multiplier for candidate generation.",
};

private static Option<int?> NumStep { get; } = new(
name: @"--num-step")
{
Description = @"Number of diffusion steps used by the voice-design model.",
};

private static Option<double?> GuidanceScale { get; } = new(
name: @"--guidance-scale")
{
Description = @"Classifier-free guidance scale. Higher values follow the prompt more strongly.",
};

private static Option<double?> InstructGuidanceScale { get; } = new(
name: @"--instruct-guidance-scale")
{
Description = @"Instruction guidance scale for prompt conditioning.",
};

private static Option<int?> Seed { get; } = new(
name: @"--seed")
{
Description = @"Optional deterministic seed for candidate generation.",
};
private static Option<string?> Input { get; } = new(@"--input")
{
Description = "Load request JSON from a file path, '-' for stdin, or an inline JSON object/array string.",
};

private static Option<string?> RequestJson { get; } = new(@"--request-json")
{
Description = "Request body as JSON.",
Hidden = true,
};

private static Option<string?> RequestFile { get; } = new(@"--request-file")
{
Description = "Path to a JSON request file, or '-' for stdin.",
Hidden = true,
};

private static string FormatResponse(ParseResult parseResult, global::FishAudio.CreateVoiceDesignResponse value, global::System.Text.Json.Serialization.JsonSerializerContext context, bool truncateLongStrings)
{
string? text = null;
CustomizeResponseText(parseResult, value, ref text);
if (!string.IsNullOrWhiteSpace(text))
{
return text;
}

var hints = new Dictionary<string, CliFormatHint>(StringComparer.OrdinalIgnoreCase)
{
};
CustomizeResponseFormatHints(hints);
return CliRuntime.FormatHumanReadable(value, context, truncateLongStrings, hints);
}

static partial void CustomizeResponseText(ParseResult parseResult, global::FishAudio.CreateVoiceDesignResponse value, ref string? text);
static partial void CustomizeResponseFormatHints(Dictionary<string, CliFormatHint> hints);


public static Command Create()
{
var command = new Command(@"create-voice-design", @"Voice Design");
command.Options.Add(Model);
command.Options.Add(Instruction);
command.Options.Add(ReferenceText);
command.Options.Add(Language);
command.Options.Add(N);
command.Options.Add(Speed);
command.Options.Add(NumStep);
command.Options.Add(GuidanceScale);
command.Options.Add(InstructGuidanceScale);
command.Options.Add(Seed);
command.Options.Add(Input);
command.Options.Add(RequestJson);
command.Options.Add(RequestFile);
command.Validators.Add(result =>
{
var hasInput = result.GetResult(Input) is not null;
var hasRequestJson = result.GetResult(RequestJson) is not null;
var hasRequestFile = result.GetResult(RequestFile) is not null;
var specifiedCount = (hasInput ? 1 : 0) + (hasRequestJson ? 1 : 0) + (hasRequestFile ? 1 : 0);
if (specifiedCount > 1)
{
result.AddError(@"Specify at most one of --input, --request-json, or --request-file.");
}
});

command.SetAction(async (ParseResult parseResult, CancellationToken cancellationToken) =>
await CliRuntime.RunAsync(async () =>
{
var __requestBase = await CliRuntime.ReadRequestOrDefaultAsync<global::FishAudio.VoiceDesignRequest>(
parseResult,
Input,
RequestJson,
RequestFile,
global::FishAudio.SourceGenerationContext.Default,
cancellationToken).ConfigureAwait(false);
var model = parseResult.GetRequiredValue(Model);
var instruction = parseResult.GetRequiredValue(Instruction);
var referenceText = CliRuntime.WasSpecified(parseResult, ReferenceText) ? parseResult.GetValue(ReferenceText) : (__requestBase is { } __ReferenceTextBaseValue ? __ReferenceTextBaseValue.ReferenceText : default);
var language = CliRuntime.WasSpecified(parseResult, Language) ? parseResult.GetValue(Language) : (__requestBase is { } __LanguageBaseValue ? __LanguageBaseValue.Language : default);
var n = CliRuntime.WasSpecified(parseResult, N) ? parseResult.GetValue(N) : (__requestBase is { } __NBaseValue ? __NBaseValue.N : default);
var speed = CliRuntime.WasSpecified(parseResult, Speed) ? parseResult.GetValue(Speed) : (__requestBase is { } __SpeedBaseValue ? __SpeedBaseValue.Speed : default);
var numStep = CliRuntime.WasSpecified(parseResult, NumStep) ? parseResult.GetValue(NumStep) : (__requestBase is { } __NumStepBaseValue ? __NumStepBaseValue.NumStep : default);
var guidanceScale = CliRuntime.WasSpecified(parseResult, GuidanceScale) ? parseResult.GetValue(GuidanceScale) : (__requestBase is { } __GuidanceScaleBaseValue ? __GuidanceScaleBaseValue.GuidanceScale : default);
var instructGuidanceScale = CliRuntime.WasSpecified(parseResult, InstructGuidanceScale) ? parseResult.GetValue(InstructGuidanceScale) : (__requestBase is { } __InstructGuidanceScaleBaseValue ? __InstructGuidanceScaleBaseValue.InstructGuidanceScale : default);
var seed = CliRuntime.WasSpecified(parseResult, Seed) ? parseResult.GetValue(Seed) : (__requestBase is { } __SeedBaseValue ? __SeedBaseValue.Seed : default);
using var client = await CliRuntime.CreateClientAsync(parseResult, cancellationToken).ConfigureAwait(false);


var response = await client.OpenAPIV1.CreateVoiceDesignAsync(
model: model,
instruction: instruction,
referenceText: referenceText,
language: language,
n: n,
speed: speed,
numStep: numStep,
guidanceScale: guidanceScale,
instructGuidanceScale: instructGuidanceScale,
seed: seed,
cancellationToken: cancellationToken).ConfigureAwait(false);


if (!await CliRuntime.TryWriteOutputDirectoryAsync(
parseResult,
response,
global::FishAudio.SourceGenerationContext.Default,
@"Candidates",
cancellationToken).ConfigureAwait(false))
{
await CliRuntime.WriteResponseAsync(
parseResult,
response,
global::FishAudio.SourceGenerationContext.Default,
FormatResponse,
cancellationToken).ConfigureAwait(false);
}
}, cancellationToken).ConfigureAwait(false));
return command;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#nullable enable

namespace FishAudio
{
public partial interface IOpenAPIV1Client
{
/// <summary>
/// Voice Design
/// </summary>
/// <param name="model">
/// Default Value: voice-design-1
/// </param>
/// <param name="request"></param>
/// <param name="requestOptions">Per-request overrides such as headers, query parameters, timeout, retries, and response buffering.</param>
/// <param name="cancellationToken">The token to cancel the operation with</param>
/// <exception cref="global::FishAudio.ApiException"></exception>
/// <remarks>
/// curl --request POST \<br/>
/// --url https://api.fish.audio/v1/voice-design \<br/>
/// --header 'Authorization: Bearer &lt;token&gt;' \<br/>
/// --header 'Content-Type: application/json' \<br/>
/// --header 'model: voice-design-1' \<br/>
/// --data '{<br/>
/// "instruction": "Warm, confident studio narrator with a natural tone",<br/>
/// "reference_text": "Welcome to Fish Audio.",<br/>
/// "language": "en",<br/>
/// "n": 2,<br/>
/// "speed": 1,<br/>
/// "num_step": 32,<br/>
/// "guidance_scale": 2,<br/>
/// "instruct_guidance_scale": 0,<br/>
/// "seed": 42<br/>
/// }'
/// </remarks>
global::System.Threading.Tasks.Task<global::FishAudio.CreateVoiceDesignResponse> CreateVoiceDesignAsync(

global::FishAudio.VoiceDesignRequest request,
string model = "voice-design-1",
global::FishAudio.AutoSDKRequestOptions? requestOptions = default,
global::System.Threading.CancellationToken cancellationToken = default);
/// <summary>
/// Voice Design
/// </summary>
/// <param name="model">
/// Default Value: voice-design-1
/// </param>
/// <param name="request"></param>
/// <param name="requestOptions">Per-request overrides such as headers, query parameters, timeout, retries, and response buffering.</param>
/// <param name="cancellationToken">The token to cancel the operation with</param>
/// <exception cref="global::FishAudio.ApiException"></exception>
/// <remarks>
/// curl --request POST \<br/>
/// --url https://api.fish.audio/v1/voice-design \<br/>
/// --header 'Authorization: Bearer &lt;token&gt;' \<br/>
/// --header 'Content-Type: application/json' \<br/>
/// --header 'model: voice-design-1' \<br/>
/// --data '{<br/>
/// "instruction": "Warm, confident studio narrator with a natural tone",<br/>
/// "reference_text": "Welcome to Fish Audio.",<br/>
/// "language": "en",<br/>
/// "n": 2,<br/>
/// "speed": 1,<br/>
/// "num_step": 32,<br/>
/// "guidance_scale": 2,<br/>
/// "instruct_guidance_scale": 0,<br/>
/// "seed": 42<br/>
/// }'
/// </remarks>
global::System.Threading.Tasks.Task<global::FishAudio.AutoSDKHttpResponse<global::FishAudio.CreateVoiceDesignResponse>> CreateVoiceDesignAsResponseAsync(

global::FishAudio.VoiceDesignRequest request,
string model = "voice-design-1",
global::FishAudio.AutoSDKRequestOptions? requestOptions = default,
global::System.Threading.CancellationToken cancellationToken = default);
/// <summary>
/// Voice Design
/// </summary>
/// <param name="model">
/// Default Value: voice-design-1
/// </param>
/// <param name="instruction">
/// Voice design prompt. Must contain 1 to 2000 characters.
/// </param>
/// <param name="referenceText">
/// Optional text used as reference content for the generated voice.<br/>
/// Default Value: openapi-json-null-sentinel-value-2BF93600-0FE4-4250-987A-E5DDB203E464
/// </param>
/// <param name="language">
/// Optional BCP-47 language hint, such as `en`, `zh`, or `ja`.<br/>
/// Default Value: openapi-json-null-sentinel-value-2BF93600-0FE4-4250-987A-E5DDB203E464
/// </param>
/// <param name="n">
/// Number of voice candidates to generate.<br/>
/// Default Value: 2
/// </param>
/// <param name="speed">
/// Speaking speed multiplier for candidate generation.<br/>
/// Default Value: 1
/// </param>
/// <param name="numStep">
/// Number of diffusion steps used by the voice-design model.<br/>
/// Default Value: 32
/// </param>
/// <param name="guidanceScale">
/// Classifier-free guidance scale. Higher values follow the prompt more strongly.<br/>
/// Default Value: 2
/// </param>
/// <param name="instructGuidanceScale">
/// Instruction guidance scale for prompt conditioning.<br/>
/// Default Value: 0
/// </param>
/// <param name="seed">
/// Optional deterministic seed for candidate generation.<br/>
/// Default Value: openapi-json-null-sentinel-value-2BF93600-0FE4-4250-987A-E5DDB203E464
/// </param>
/// <param name="requestOptions">Per-request overrides such as headers, query parameters, timeout, retries, and response buffering.</param>
/// <param name="cancellationToken">The token to cancel the operation with</param>
/// <exception cref="global::System.InvalidOperationException"></exception>
global::System.Threading.Tasks.Task<global::FishAudio.CreateVoiceDesignResponse> CreateVoiceDesignAsync(
string instruction,
string model = "voice-design-1",
string? referenceText = default,
string? language = default,
int? n = default,
double? speed = default,
int? numStep = default,
double? guidanceScale = default,
double? instructGuidanceScale = default,
int? seed = default,
global::FishAudio.AutoSDKRequestOptions? requestOptions = default,
global::System.Threading.CancellationToken cancellationToken = default);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#nullable enable

namespace FishAudio.JsonConverters
{
/// <inheritdoc />
public sealed class CreateVoiceDesignResponseItemInJsonConverter : global::System.Text.Json.Serialization.JsonConverter<global::FishAudio.CreateVoiceDesignResponseItemIn>
{
/// <inheritdoc />
public override global::FishAudio.CreateVoiceDesignResponseItemIn Read(
ref global::System.Text.Json.Utf8JsonReader reader,
global::System.Type typeToConvert,
global::System.Text.Json.JsonSerializerOptions options)
{
switch (reader.TokenType)
{
case global::System.Text.Json.JsonTokenType.String:
{
var stringValue = reader.GetString();
if (stringValue != null)
{
return global::FishAudio.CreateVoiceDesignResponseItemInExtensions.ToEnum(stringValue) ?? default;
}

break;
}
case global::System.Text.Json.JsonTokenType.Number:
{
var numValue = reader.GetInt32();
return (global::FishAudio.CreateVoiceDesignResponseItemIn)numValue;
}
case global::System.Text.Json.JsonTokenType.Null:
{
return default(global::FishAudio.CreateVoiceDesignResponseItemIn);
}
default:
throw new global::System.ArgumentOutOfRangeException(nameof(reader));
}

return default;
}

/// <inheritdoc />
public override void Write(
global::System.Text.Json.Utf8JsonWriter writer,
global::FishAudio.CreateVoiceDesignResponseItemIn value,
global::System.Text.Json.JsonSerializerOptions options)
{
writer = writer ?? throw new global::System.ArgumentNullException(nameof(writer));

writer.WriteStringValue(global::FishAudio.CreateVoiceDesignResponseItemInExtensions.ToValueString(value));
}
}
}
Loading