mirror of
https://github.com/modelstudioai/cli.git
synced 2026-09-14 19:49:23 +08:00
feat(config): add profile-level watermark setting
This commit is contained in:
@@ -12,9 +12,9 @@ export default defineCommand({
|
||||
valueHint: "<key>",
|
||||
description: {
|
||||
"en-US":
|
||||
"Config key (language, base_url, output, output_dir, timeout, api_key, api_key_capabilities, access_token, access_key_id, access_key_secret, security_token, default_*_model, workspace_id)",
|
||||
"Config key (language, base_url, output, output_dir, timeout, watermark, api_key, api_key_capabilities, access_token, access_key_id, access_key_secret, security_token, default_*_model, workspace_id)",
|
||||
"zh-CN":
|
||||
"配置项名称(language、base_url、output、output_dir、timeout、api_key、api_key_capabilities、access_token、access_key_id、access_key_secret、security_token、default_*_model、workspace_id)",
|
||||
"配置项名称(language、base_url、output、output_dir、timeout、watermark、api_key、api_key_capabilities、access_token、access_key_id、access_key_secret、security_token、default_*_model、workspace_id)",
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
@@ -29,6 +29,7 @@ export default defineCommand({
|
||||
"--key language --value zh-CN",
|
||||
"--key output --value json",
|
||||
"--key timeout --value 600",
|
||||
"--key watermark --value false",
|
||||
"--key base_url --value https://dashscope.aliyuncs.com",
|
||||
"--config company-plan --key api-key-capabilities --value text.chat,image.generate",
|
||||
],
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
ExitCode,
|
||||
isApiKeyCapability,
|
||||
normalizeModelBaseUrl,
|
||||
parseBooleanValue,
|
||||
SUPPORTED_LANGUAGES,
|
||||
} from "bailian-cli-core";
|
||||
|
||||
@@ -13,6 +14,7 @@ export const VALID_KEYS = [
|
||||
"output",
|
||||
"output_dir",
|
||||
"timeout",
|
||||
"watermark",
|
||||
"api_key",
|
||||
"access_token",
|
||||
"access_key_id",
|
||||
@@ -62,7 +64,7 @@ export const UI_ENUM_KEYS: Record<string, string[]> = {
|
||||
};
|
||||
|
||||
// Keys the UI renders as a true/false dropdown and stores as a boolean.
|
||||
export const UI_BOOLEAN_KEYS = new Set<string>(["telemetry"]);
|
||||
export const UI_BOOLEAN_KEYS = new Set<string>(["telemetry", "watermark"]);
|
||||
|
||||
// Default model each `default_*_model` key falls back to when left unset. These
|
||||
// mirror the inline `|| "<model>"` fallbacks in the generation commands
|
||||
@@ -164,7 +166,10 @@ export function resolveKey(key: string): string {
|
||||
* Validate a single config entry and coerce its value to the stored type.
|
||||
* Throws BailianError(USAGE) for unknown keys or invalid values.
|
||||
*/
|
||||
export function validateAndCoerce(key: string, value: string): string | number | string[] {
|
||||
export function validateAndCoerce(
|
||||
key: string,
|
||||
value: string,
|
||||
): string | number | boolean | string[] {
|
||||
const resolvedKey = resolveKey(key);
|
||||
|
||||
if (!(VALID_KEYS as readonly string[]).includes(resolvedKey)) {
|
||||
@@ -201,6 +206,8 @@ export function validateAndCoerce(key: string, value: string): string | number |
|
||||
|
||||
if (resolvedKey === "base_url") return normalizeModelBaseUrl(value);
|
||||
|
||||
if (resolvedKey === "watermark") return parseBooleanValue(value, "watermark");
|
||||
|
||||
if (resolvedKey === "api_key_capabilities") {
|
||||
let rawCapabilities: unknown;
|
||||
if (value.trim().startsWith("[")) {
|
||||
|
||||
@@ -18,6 +18,7 @@ export default defineCommand({
|
||||
base_url: client.baseUrl,
|
||||
output: settings.output,
|
||||
timeout: settings.timeout,
|
||||
watermark: settings.watermark,
|
||||
config: settings.configName ?? "default",
|
||||
config_file: store.path,
|
||||
};
|
||||
|
||||
@@ -207,7 +207,7 @@ export default defineCommand({
|
||||
"prompt-extend",
|
||||
);
|
||||
|
||||
const watermark = resolveWatermark(flags.watermark);
|
||||
const watermark = resolveWatermark(flags.watermark, settings.watermark);
|
||||
|
||||
const parameters: NonNullable<DashScopeImageRequest["parameters"]> = {
|
||||
size: resolveImageSize(flags.size, route.sizeProfile),
|
||||
|
||||
@@ -185,7 +185,7 @@ export default defineCommand({
|
||||
"prompt-extend",
|
||||
);
|
||||
|
||||
const watermark = resolveWatermark(flags.watermark);
|
||||
const watermark = resolveWatermark(flags.watermark, settings.watermark);
|
||||
|
||||
const parameters: NonNullable<DashScopeImageRequest["parameters"]> = {
|
||||
size,
|
||||
|
||||
@@ -197,7 +197,7 @@ export default defineCommand({
|
||||
|
||||
// --- Build request body ---
|
||||
const promptExtend = resolveBooleanFlag(flags.promptExtend, undefined, "prompt-extend");
|
||||
const watermark = resolveWatermark(flags.watermark);
|
||||
const watermark = resolveWatermark(flags.watermark, settings.watermark);
|
||||
|
||||
const body: DashScopeVideoEditRequest = {
|
||||
model,
|
||||
|
||||
@@ -208,7 +208,7 @@ export default defineCommand({
|
||||
resolvedFileUrl = await ctx.client.uploadFile(fileUrl, model);
|
||||
}
|
||||
|
||||
const watermark = resolveWatermark(flags.watermark);
|
||||
const watermark = resolveWatermark(flags.watermark, settings.watermark);
|
||||
const promptExtend = resolveBooleanFlag(flags.promptExtend, undefined, "prompt-extend");
|
||||
|
||||
const body: DashScopeVideoRequest = {
|
||||
|
||||
@@ -249,7 +249,7 @@ export default defineCommand({
|
||||
|
||||
// --- Build request body ---
|
||||
const promptExtend = resolveBooleanFlag(flags.promptExtend, undefined, "prompt-extend");
|
||||
const watermark = resolveWatermark(flags.watermark);
|
||||
const watermark = resolveWatermark(flags.watermark, settings.watermark);
|
||||
|
||||
const body: DashScopeVideoRefRequest = {
|
||||
model,
|
||||
|
||||
@@ -33,3 +33,9 @@ test("default-speech-recognition-model alias accepts an ASR model ID", () => {
|
||||
"qwen-audio-3.0-asr-flash",
|
||||
);
|
||||
});
|
||||
|
||||
test("watermark config accepts only boolean text and stores a boolean", () => {
|
||||
expect(validateAndCoerce("watermark", "false")).toBe(false);
|
||||
expect(validateAndCoerce("watermark", "TRUE")).toBe(true);
|
||||
expect(() => validateAndCoerce("watermark", "yes")).toThrow(/true or false/i);
|
||||
});
|
||||
|
||||
@@ -200,8 +200,10 @@ test("GET /api/config 返回全部 profile、明文密钥与持久化激活项",
|
||||
expect(res.json.keys).toContain("console_site");
|
||||
expect(res.json.keys).toContain("telemetry");
|
||||
expect(res.json.keys).toContain("default_speech_recognition_model");
|
||||
expect(res.json.keys).toContain("watermark");
|
||||
expect(res.json.enums.console_site).toEqual(["domestic", "international"]);
|
||||
expect(res.json.booleanKeys).toContain("telemetry");
|
||||
expect(res.json.booleanKeys).toContain("watermark");
|
||||
// Default field hints are surfaced as prefilled values in the UI.
|
||||
expect(res.json.fieldDefaults.default_image_model).toBe("qwen-image-3.0");
|
||||
expect(res.json.fieldDefaults.default_text_model).toBe("qwen3.8-max");
|
||||
|
||||
@@ -64,10 +64,53 @@ describe("e2e: config", () => {
|
||||
config_file?: string;
|
||||
base_url?: string;
|
||||
timeout?: number;
|
||||
watermark?: boolean;
|
||||
}>(stdout);
|
||||
expect(data.config_file).toBeDefined();
|
||||
expect(data.base_url).toBeDefined();
|
||||
expect(data.timeout).toBeDefined();
|
||||
expect(data.watermark).toBe(true);
|
||||
});
|
||||
|
||||
test("config set 将 watermark 作为 boolean 写入并由 config show 读回", async () => {
|
||||
const configDir = mkdtempSync(join(tmpdir(), "bl-config-watermark-"));
|
||||
try {
|
||||
const env = { BAILIAN_CONFIG_DIR: configDir };
|
||||
const setResult = await runCommandE2e(
|
||||
CONFIG_ROUTES,
|
||||
[
|
||||
"config",
|
||||
"set",
|
||||
"--config",
|
||||
"media",
|
||||
"--key",
|
||||
"watermark",
|
||||
"--value",
|
||||
"false",
|
||||
"--output",
|
||||
"json",
|
||||
],
|
||||
env,
|
||||
);
|
||||
expect(setResult.exitCode, setResult.stderr).toBe(0);
|
||||
expect(parseStdoutJson<{ watermark?: boolean }>(setResult.stdout).watermark).toBe(false);
|
||||
|
||||
const persisted = JSON.parse(readFileSync(join(configDir, "config.json"), "utf8")) as Record<
|
||||
string,
|
||||
Record<string, unknown>
|
||||
>;
|
||||
expect(persisted.media?.watermark).toBe(false);
|
||||
|
||||
const showResult = await runCommandE2e(
|
||||
CONFIG_ROUTES,
|
||||
["config", "show", "--config", "media", "--output", "json"],
|
||||
env,
|
||||
);
|
||||
expect(showResult.exitCode, showResult.stderr).toBe(0);
|
||||
expect(parseStdoutJson<{ watermark?: boolean }>(showResult.stdout).watermark).toBe(false);
|
||||
} finally {
|
||||
rmSync(configDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("config show --output text", async () => {
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { describe, expect, test } from "vite-plus/test";
|
||||
import { parseStdoutJson, runCommandE2e } from "./helpers.ts";
|
||||
import { IMAGE_ROUTES, VIDEO_ROUTES, type E2eRouteExports } from "./topic-routes.ts";
|
||||
|
||||
interface WatermarkScenario {
|
||||
name: string;
|
||||
routes: E2eRouteExports;
|
||||
args: string[];
|
||||
}
|
||||
|
||||
const scenarios: WatermarkScenario[] = [
|
||||
{
|
||||
name: "image generate",
|
||||
routes: IMAGE_ROUTES,
|
||||
args: ["image", "generate", "--prompt", "A cat"],
|
||||
},
|
||||
{
|
||||
name: "image edit",
|
||||
routes: IMAGE_ROUTES,
|
||||
args: [
|
||||
"image",
|
||||
"edit",
|
||||
"--image",
|
||||
"https://example.com/input.png",
|
||||
"--prompt",
|
||||
"Blue background",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "video generate",
|
||||
routes: VIDEO_ROUTES,
|
||||
args: ["video", "generate", "--prompt", "A cat waves"],
|
||||
},
|
||||
{
|
||||
name: "video edit",
|
||||
routes: VIDEO_ROUTES,
|
||||
args: ["video", "edit", "--video", "https://example.com/input.mp4", "--prompt", "Warm colors"],
|
||||
},
|
||||
{
|
||||
name: "video ref",
|
||||
routes: VIDEO_ROUTES,
|
||||
args: [
|
||||
"video",
|
||||
"ref",
|
||||
"--image",
|
||||
"https://example.com/person.png",
|
||||
"--prompt",
|
||||
"Image 1 waves",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
describe("e2e: global watermark config", () => {
|
||||
for (const scenario of scenarios) {
|
||||
test(`${scenario.name} uses watermark=false from the selected Profile`, async () => {
|
||||
const configDir = mkdtempSync(join(tmpdir(), "bl-watermark-profile-"));
|
||||
try {
|
||||
writeFileSync(
|
||||
join(configDir, "config.json"),
|
||||
JSON.stringify({ media: { watermark: false } }, null, 2) + "\n",
|
||||
);
|
||||
const { stdout, stderr, exitCode } = await runCommandE2e(
|
||||
scenario.routes,
|
||||
[...scenario.args, "--config", "media", "--dry-run", "--output", "json"],
|
||||
{ BAILIAN_CONFIG_DIR: configDir },
|
||||
);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
const data = parseStdoutJson<{
|
||||
request?: { parameters?: { watermark?: boolean } };
|
||||
}>(stdout);
|
||||
expect(data.request?.parameters?.watermark).toBe(false);
|
||||
} finally {
|
||||
rmSync(configDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -272,6 +272,7 @@ export function buildSettings(s: ResolutionSources): Settings {
|
||||
outputExplicit: Boolean(flags.output || env.DASHSCOPE_OUTPUT || file.output),
|
||||
outputDir: file.output_dir || undefined,
|
||||
timeout,
|
||||
watermark: file.watermark ?? true,
|
||||
defaultTextModel: file.default_text_model,
|
||||
defaultVideoModel: file.default_video_model,
|
||||
defaultImageToVideoModel: file.default_image_to_video_model,
|
||||
|
||||
@@ -35,6 +35,7 @@ export interface ConfigFile {
|
||||
output?: "text" | "json";
|
||||
output_dir?: string;
|
||||
timeout?: number;
|
||||
watermark?: boolean;
|
||||
default_text_model?: string;
|
||||
default_video_model?: string;
|
||||
default_image_to_video_model?: string;
|
||||
@@ -63,6 +64,7 @@ export const CONFIG_FILE_KEYS = [
|
||||
"output",
|
||||
"output_dir",
|
||||
"timeout",
|
||||
"watermark",
|
||||
"default_text_model",
|
||||
"default_video_model",
|
||||
"default_image_to_video_model",
|
||||
@@ -156,6 +158,7 @@ export function parseConfigFile(raw: unknown): ConfigFile {
|
||||
if (typeof obj.output_dir === "string" && obj.output_dir.length > 0)
|
||||
out.output_dir = obj.output_dir;
|
||||
if (typeof obj.timeout === "number" && obj.timeout > 0) out.timeout = obj.timeout;
|
||||
if (typeof obj.watermark === "boolean") out.watermark = obj.watermark;
|
||||
if (typeof obj.default_text_model === "string" && obj.default_text_model.length > 0)
|
||||
out.default_text_model = obj.default_text_model;
|
||||
if (typeof obj.default_video_model === "string" && obj.default_video_model.length > 0)
|
||||
@@ -224,6 +227,7 @@ export interface Settings {
|
||||
outputExplicit: boolean;
|
||||
outputDir?: string;
|
||||
timeout: number;
|
||||
watermark: boolean;
|
||||
defaultTextModel?: string;
|
||||
defaultVideoModel?: string;
|
||||
defaultImageToVideoModel?: string;
|
||||
|
||||
@@ -34,7 +34,7 @@ export function resolveBooleanFlag(
|
||||
return defaultWhenUnset;
|
||||
}
|
||||
|
||||
/** Resolve `--watermark` flag; default true when unset. */
|
||||
export function resolveWatermark(flagValue: unknown): boolean {
|
||||
return parseOptionalBooleanValue(flagValue, "watermark") ?? true;
|
||||
/** Resolve `--watermark`; command flag overrides config, then defaults to true. */
|
||||
export function resolveWatermark(flagValue: unknown, configuredValue?: boolean): boolean {
|
||||
return parseOptionalBooleanValue(flagValue, "watermark") ?? configuredValue ?? true;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,14 @@ test("default_speech_recognition_model 从配置文件进入运行时 Settings",
|
||||
expect(resolve({ file }).defaultSpeechRecognitionModel).toBe("qwen-audio-3.0-asr-flash");
|
||||
});
|
||||
|
||||
test("watermark 从配置文件进入 Settings,缺省时保持合规默认值 true", () => {
|
||||
expect(parseConfigFile({ watermark: false }).watermark).toBe(false);
|
||||
expect(parseConfigFile({ watermark: true }).watermark).toBe(true);
|
||||
expect(parseConfigFile({ watermark: "false" }).watermark).toBeUndefined();
|
||||
expect(resolve({ file: { watermark: false } }).watermark).toBe(false);
|
||||
expect(resolve({}).watermark).toBe(true);
|
||||
});
|
||||
|
||||
test("baseUrl:flag > env > file > 默认,所有来源统一归一化", () => {
|
||||
const flags = { baseUrl: "https://flag.example.com/compatible-mode/v1?source=flag" };
|
||||
const env = { DASHSCOPE_BASE_URL: "https://env.example.com/apps/anthropic#env" };
|
||||
|
||||
@@ -28,6 +28,7 @@ function makeSettings(configName?: string): Settings {
|
||||
output: "json",
|
||||
outputExplicit: false,
|
||||
timeout: 30,
|
||||
watermark: true,
|
||||
verbose: false,
|
||||
quiet: true,
|
||||
dryRun: false,
|
||||
|
||||
@@ -31,6 +31,7 @@ function testDeps(identity: Partial<Identity> = {}): {
|
||||
output: "json",
|
||||
outputExplicit: true,
|
||||
timeout: 30,
|
||||
watermark: true,
|
||||
verbose: false,
|
||||
quiet: true,
|
||||
dryRun: false,
|
||||
@@ -290,6 +291,9 @@ test("resolveWatermark uses flag or defaults to true", () => {
|
||||
expect(resolveWatermark("false")).toBe(false);
|
||||
expect(resolveWatermark("true")).toBe(true);
|
||||
expect(resolveWatermark(undefined)).toBe(true);
|
||||
expect(resolveWatermark(undefined, false)).toBe(false);
|
||||
expect(resolveWatermark("true", false)).toBe(true);
|
||||
expect(resolveWatermark("false", true)).toBe(false);
|
||||
});
|
||||
|
||||
test("resolveBooleanFlag uses flag or defaultWhenUnset", () => {
|
||||
|
||||
@@ -23,6 +23,7 @@ function testDeps(overrides?: Partial<Settings>): { identity: Identity; settings
|
||||
output: "json",
|
||||
outputExplicit: true,
|
||||
timeout: 5,
|
||||
watermark: true,
|
||||
verbose: false,
|
||||
quiet: true,
|
||||
dryRun: false,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/** Shared --foo <bool> help text; keep wording consistent with actual CLI/request behavior. */
|
||||
|
||||
export const BOOL_FLAG_WATERMARK = {
|
||||
"en-US": "Enable watermark (true/false). Omit flag to use CLI default (true).",
|
||||
"zh-CN": "是否启用水印(true/false)。不传时使用 CLI 默认值 true。",
|
||||
"en-US":
|
||||
"Enable watermark (true/false). Omit flag to use the Profile setting or CLI default (true).",
|
||||
"zh-CN": "是否启用水印(true/false)。不传时使用 Profile 配置或 CLI 默认值 true。",
|
||||
};
|
||||
|
||||
/** CLI sends prompt_extend=true when flag omitted (qwen-image edit, etc.). */
|
||||
|
||||
@@ -88,10 +88,10 @@ bl config list --output json
|
||||
|
||||
#### Flags
|
||||
|
||||
| Flag | Type | Required | Description |
|
||||
| ----------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--key <key>` | string | yes | Config key (language, base*url, output, output_dir, timeout, api_key, api_key_capabilities, access_token, access_key_id, access_key_secret, security_token, default*\*\_model, workspace_id) |
|
||||
| `--value <value>` | string | yes | Value to set |
|
||||
| Flag | Type | Required | Description |
|
||||
| ----------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--key <key>` | string | yes | Config key (language, base*url, output, output_dir, timeout, watermark, api_key, api_key_capabilities, access_token, access_key_id, access_key_secret, security_token, default*\*\_model, workspace_id) |
|
||||
| `--value <value>` | string | yes | Value to set |
|
||||
|
||||
#### Examples
|
||||
|
||||
@@ -107,6 +107,10 @@ bl config set --key output --value json
|
||||
bl config set --key timeout --value 600
|
||||
```
|
||||
|
||||
```bash
|
||||
bl config set --key watermark --value false
|
||||
```
|
||||
|
||||
```bash
|
||||
bl config set --key base_url --value https://dashscope.aliyuncs.com
|
||||
```
|
||||
|
||||
@@ -36,7 +36,7 @@ Index: [index.md](index.md)
|
||||
| `--negative-prompt <text>` | string | no | Negative prompt to exclude unwanted content |
|
||||
| `--function <name>` | string | no | wanx\*-imageedit function (default: description_edit). Examples: stylization_all, description_edit |
|
||||
| `--prompt-extend <bool>` | boolean | no | Enable prompt extend (true/false). Omit flag to use CLI default (true). |
|
||||
| `--watermark <bool>` | boolean | no | Enable watermark (true/false). Omit flag to use CLI default (true). |
|
||||
| `--watermark <bool>` | boolean | no | Enable watermark (true/false). Omit flag to use the Profile setting or CLI default (true). |
|
||||
| `--out-dir <dir>` | string | no | Download images to directory |
|
||||
| `--out-prefix <prefix>` | string | no | Filename prefix (default: edited) |
|
||||
| `--async` | switch | no | Return async task id without waiting |
|
||||
@@ -99,7 +99,7 @@ bl image edit --image ./photo.png --prompt "Replace the background with a beach"
|
||||
| `--seed <n>` | number | no | Random seed for reproducible generation |
|
||||
| `--negative-prompt <text>` | string | no | Negative prompt to exclude unwanted content |
|
||||
| `--prompt-extend <bool>` | boolean | no | Enable prompt extend (true/false). Omit flag: true for qwen-image sync; parameter omitted on async models (API default). |
|
||||
| `--watermark <bool>` | boolean | no | Enable watermark (true/false). Omit flag to use CLI default (true). |
|
||||
| `--watermark <bool>` | boolean | no | Enable watermark (true/false). Omit flag to use the Profile setting or CLI default (true). |
|
||||
| `--async` | switch | no | Return async task id without waiting |
|
||||
| `--concurrent <n>` | number | no | Run N parallel requests (default: 1) |
|
||||
| `--out-dir <dir>` | string | no | Download images to directory |
|
||||
|
||||
@@ -56,26 +56,26 @@ bl video download --task-id 3b256896-xxxx --out video.mp4 --quiet
|
||||
|
||||
#### Flags
|
||||
|
||||
| Flag | Type | Required | Description |
|
||||
| -------------------------------- | ------- | -------- | --------------------------------------------------------------------------------------- |
|
||||
| `--model <model>` | string | no | Model ID (default: happyhorse-1.0-video-edit) |
|
||||
| `--video <url>` | string | yes | Input video URL or local file (mp4/mov, 2-10s) |
|
||||
| `--prompt <text>` | string | no | Edit instruction (e.g. "Convert the scene to a claymation style") |
|
||||
| `--ref-image <url>` | string | no | Reference image URL (up to 4, comma-separated) |
|
||||
| `--negative-prompt <text>` | string | no | Negative prompt to exclude unwanted content |
|
||||
| `--resolution <res>` | string | no | Resolution: 720P or 1080P (default: 1080P) |
|
||||
| `--ratio <ratio>` | string | no | Aspect ratio (16:9, 9:16, 1:1, 4:3, 3:4) |
|
||||
| `--duration <seconds>` | number | no | Output video duration in seconds (2-10) |
|
||||
| `--audio-setting <auto\|origin>` | string | no | Audio: auto (default) or origin (keep original) |
|
||||
| `--prompt-extend <bool>` | boolean | no | Enable prompt extend (true/false). Omit flag to omit the parameter (DashScope default). |
|
||||
| `--watermark <bool>` | boolean | no | Enable watermark (true/false). Omit flag to use CLI default (true). |
|
||||
| `--seed <n>` | number | no | Random seed for reproducible generation |
|
||||
| `--download <path>` | string | no | Save video to file on completion |
|
||||
| `--async` | switch | no | Return async task id without waiting |
|
||||
| `--concurrent <n>` | number | no | Run N parallel requests (default: 1) |
|
||||
| `--poll-interval <seconds>` | number | no | Polling interval when waiting (default: 15) |
|
||||
| `--api-key <key>` | string | no | API key |
|
||||
| `--base-url <url>` | string | no | API base URL |
|
||||
| Flag | Type | Required | Description |
|
||||
| -------------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------ |
|
||||
| `--model <model>` | string | no | Model ID (default: happyhorse-1.0-video-edit) |
|
||||
| `--video <url>` | string | yes | Input video URL or local file (mp4/mov, 2-10s) |
|
||||
| `--prompt <text>` | string | no | Edit instruction (e.g. "Convert the scene to a claymation style") |
|
||||
| `--ref-image <url>` | string | no | Reference image URL (up to 4, comma-separated) |
|
||||
| `--negative-prompt <text>` | string | no | Negative prompt to exclude unwanted content |
|
||||
| `--resolution <res>` | string | no | Resolution: 720P or 1080P (default: 1080P) |
|
||||
| `--ratio <ratio>` | string | no | Aspect ratio (16:9, 9:16, 1:1, 4:3, 3:4) |
|
||||
| `--duration <seconds>` | number | no | Output video duration in seconds (2-10) |
|
||||
| `--audio-setting <auto\|origin>` | string | no | Audio: auto (default) or origin (keep original) |
|
||||
| `--prompt-extend <bool>` | boolean | no | Enable prompt extend (true/false). Omit flag to omit the parameter (DashScope default). |
|
||||
| `--watermark <bool>` | boolean | no | Enable watermark (true/false). Omit flag to use the Profile setting or CLI default (true). |
|
||||
| `--seed <n>` | number | no | Random seed for reproducible generation |
|
||||
| `--download <path>` | string | no | Save video to file on completion |
|
||||
| `--async` | switch | no | Return async task id without waiting |
|
||||
| `--concurrent <n>` | number | no | Run N parallel requests (default: 1) |
|
||||
| `--poll-interval <seconds>` | number | no | Polling interval when waiting (default: 15) |
|
||||
| `--api-key <key>` | string | no | API key |
|
||||
| `--base-url <url>` | string | no | API base URL |
|
||||
|
||||
#### Examples
|
||||
|
||||
@@ -117,7 +117,7 @@ bl video edit --video https://example.com/input.mp4 --prompt "Put clothes on the
|
||||
| `--ratio <ratio>` | string | no | Aspect ratio (e.g. 16:9, 9:16, 1:1) |
|
||||
| `--duration <seconds>` | number | no | Video duration in seconds (default: 5) |
|
||||
| `--prompt-extend <bool>` | boolean | no | Enable prompt extend (true/false). Omit flag to omit the parameter (DashScope default). |
|
||||
| `--watermark <bool>` | boolean | no | Enable watermark (true/false). Omit flag to use CLI default (true). |
|
||||
| `--watermark <bool>` | boolean | no | Enable watermark (true/false). Omit flag to use the Profile setting or CLI default (true). |
|
||||
| `--seed <n>` | number | no | Random seed for reproducible generation |
|
||||
| `--download <path>` | string | no | Save video to file on completion |
|
||||
| `--file <url-or-path>` | string | no | Reference file URL or local path for file-to-video (wan3.0-video only; mutually exclusive with --image/--last-frame) |
|
||||
@@ -172,7 +172,7 @@ bl video generate --prompt "A cat playing with a ball" --watermark false
|
||||
| `--ratio <ratio>` | string | no | Aspect ratio (16:9, 9:16, 1:1) |
|
||||
| `--duration <seconds>` | number | no | Video duration in seconds (default: 5) |
|
||||
| `--prompt-extend <bool>` | boolean | no | Enable prompt extend (true/false). Omit flag to omit the parameter (DashScope default). |
|
||||
| `--watermark <bool>` | boolean | no | Enable watermark (true/false). Omit flag to use CLI default (true). |
|
||||
| `--watermark <bool>` | boolean | no | Enable watermark (true/false). Omit flag to use the Profile setting or CLI default (true). |
|
||||
| `--seed <n>` | number | no | Random seed for reproducible generation |
|
||||
| `--download <path>` | string | no | Save video to file on completion |
|
||||
| `--async` | switch | no | Return async task id without waiting |
|
||||
|
||||
Reference in New Issue
Block a user