skillfree 0.1.14 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/skillfree.js CHANGED
@@ -39,6 +39,7 @@ program
39
39
  .option('--voice <voice>', 'TTS 声音(默认 nova)')
40
40
  .option('--size <size>', '图像尺寸(默认 1024x1024)')
41
41
  .option('--duration <sec>', '视频/音乐时长(秒)')
42
+ .option('--lyrics <text>', '歌词(music-2.5 用,支持 [verse][chorus] 标签)')
42
43
  .action(async (flags) => {
43
44
  const { pilot } = require('../scripts/commands/pilot')
44
45
  await pilot(flags).catch(e => { console.error('❌', e.message); process.exit(1) })
@@ -85,7 +86,11 @@ program
85
86
  // Suno 任务用 suno:xxx 格式区分
86
87
  if (taskId.startsWith('suno:')) {
87
88
  const sunoId = taskId.slice(5)
88
- const poll = await request('/suno/fetch/' + sunoId, { method: 'GET' })
89
+ const { BASE_URL, getApiKey } = require('../scripts/lib/client')
90
+ const apiKey = getApiKey()
91
+ const poll = await fetch(`${BASE_URL}/suno/fetch/${sunoId}`, {
92
+ headers: { 'Authorization': `Bearer ${apiKey}` }
93
+ })
89
94
  const result = await poll.json()
90
95
  if (result.code !== 'success') throw new Error(result.message || JSON.stringify(result))
91
96
  const status = result.data?.status
@@ -115,10 +120,11 @@ program
115
120
  console.log(`\n📋 任务 ${taskId}`)
116
121
  console.log(` 状态:${task.status}`)
117
122
  console.log(` 模型:${task.model}`)
118
- if (task.status === 'completed' && task.output_url) {
119
- console.log(` 链接:${task.output_url}`)
123
+ const videoUrl = task.result_url || task.output_url
124
+ if (task.status === 'completed' && videoUrl) {
125
+ console.log(` 链接:${videoUrl}`)
120
126
  if (flags.output) {
121
- const resp = await fetch(task.output_url)
127
+ const resp = await fetch(videoUrl)
122
128
  fs.writeFileSync(flags.output, Buffer.from(await resp.arrayBuffer()))
123
129
  console.log(`✅ 已下载到 ${flags.output}`)
124
130
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillfree",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "🦞 一个 API,满足所有龙虾技能需求",
5
5
  "main": "bin/skillfree.js",
6
6
  "bin": {
@@ -143,11 +143,12 @@ async function pilot(flags) {
143
143
  else console.log(`✅ TTS 成功,时长约 ${(data.extra_info?.audio_length / 1000).toFixed(1)} 秒`)
144
144
 
145
145
  } else if (ttsModel === 'gemini-2.5-pro-preview-tts' || ttsModel === 'gemini-2.5-flash-preview-tts') {
146
- // Gemini TTS:走 /v1beta/models/:id:generateContent,认证无 Bearer
146
+ // Gemini TTS:走 skillfree.tech 后端 /v1beta 路由
147
+ // 注意:用 fetch+BASE_URL 而非 request(),因为 request() 会自动加 /v1 前缀
147
148
  const apiKey = getApiKey()
148
- const res = await fetch(BASE_URL.replace('skillfree.tech', 'dmxapi.cn') + '/v1beta/models/' + ttsModel + ':generateContent', {
149
+ const res = await fetch(BASE_URL + '/v1beta/models/' + ttsModel + ':generateContent', {
149
150
  method: 'POST',
150
- headers: { 'Authorization': apiKey, 'Content-Type': 'application/json' },
151
+ headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
151
152
  body: JSON.stringify({
152
153
  contents: [{ parts: [{ text }] }],
153
154
  generationConfig: {
@@ -192,10 +193,11 @@ async function pilot(flags) {
192
193
  const musicModel = model || 'chirp-v5'
193
194
 
194
195
  if (musicModel === 'chirp-v5') {
195
- // Suno 异步接口
196
- const res = await request('/suno/submit/music', {
196
+ // Suno 异步接口(路由在 /suno/,不在 /v1/ 下,需用 BASE_URL 直接请求)
197
+ const apiKey = getApiKey()
198
+ const res = await fetch(`${BASE_URL}/suno/submit/music`, {
197
199
  method: 'POST',
198
- headers: { 'Accept': 'application/json' },
200
+ headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': `Bearer ${apiKey}` },
199
201
  body: JSON.stringify({
200
202
  gpt_description_prompt: prompt,
201
203
  make_instrumental: true,
@@ -211,7 +213,9 @@ async function pilot(flags) {
211
213
  // 轮询结果
212
214
  for (let i = 0; i < 15; i++) {
213
215
  await new Promise(r => setTimeout(r, 10000))
214
- const poll = await request('/suno/fetch/' + taskId, { method: 'GET' })
216
+ const poll = await fetch(`${BASE_URL}/suno/fetch/${taskId}`, {
217
+ headers: { 'Authorization': `Bearer ${apiKey}` }
218
+ })
215
219
  const result = await poll.json()
216
220
  if (result.code !== 'success') throw new Error(result.message || JSON.stringify(result))
217
221
  const status = result.data?.status
@@ -365,7 +369,7 @@ async function pilot(flags) {
365
369
 
366
370
  if (status === 'completed') {
367
371
  console.log('\n')
368
- const videoUrl = task.output_url
372
+ const videoUrl = task.result_url || task.output_url
369
373
  if (!videoUrl) throw new Error('任务完成但未返回视频 URL: ' + JSON.stringify(task))
370
374
 
371
375
  if (output) {