tuna-agent 0.1.156 → 0.1.157

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.
@@ -144,6 +144,22 @@ function detectPlatform(url) {
144
144
  return 'facebook';
145
145
  return 'other';
146
146
  }
147
+ // yt-dlp `%(title)s` is a clean title on YouTube but the full post caption
148
+ // on TikTok/Douyin/Facebook (often 200+ chars, prefixed with engagement
149
+ // stats). Strip the social-stats prefix, keep the first segment, and cap
150
+ // to a sane title length so the cloned idea doesn't get a paragraph title.
151
+ function cleanSourceTitle(raw) {
152
+ let t = (raw || '').trim().split('\n')[0].trim();
153
+ // Drop leading "1K views · 51 reactions | " / "230 likes, 12 comments - " noise.
154
+ t = t.replace(/^\s*(?:[\d.,]+\s*[KMB]?\s*(?:views?|likes?|reactions?|comments?|shares?|followers?)\b\s*[·,|–\-:]*\s*)+/i, '').trim();
155
+ // FB/TikTok pack "title | extra | hashtags" — keep the first real segment.
156
+ const seg = t.split(/\s*[|·]\s*/)[0].trim();
157
+ if (seg.length >= 8)
158
+ t = seg;
159
+ if (t.length > 90)
160
+ t = t.slice(0, 90).replace(/\s+\S*$/, '').trim() + '…';
161
+ return t.slice(0, 120);
162
+ }
147
163
  // Download a source video across YouTube / TikTok / Douyin / Facebook.
148
164
  // yt-dlp supports all of them, but a single rigid `-f` that works for
149
165
  // YouTube fails on the others, so try a tolerant 720p-capped format then
@@ -153,6 +169,10 @@ async function downloadSourceVideo(url, dest) {
153
169
  const platform = detectPlatform(url);
154
170
  const common = [
155
171
  '--no-playlist', '--no-warnings', '--retries', '3', '--fragment-retries', '3',
172
+ // dest ends in .mp4 — force merged/odd containers to mp4 so the file
173
+ // lands EXACTLY at `dest` (else fs.rename → ENOENT, e.g. YouTube shorts
174
+ // where bv*+ba merges to .mkv/.webm).
175
+ '--merge-output-format', 'mp4', '--remux-video', 'mp4',
156
176
  '--user-agent', SRC_UA, ...cookieArgs(), '-o', dest, url,
157
177
  ];
158
178
  const attempts = [
@@ -522,7 +542,7 @@ export async function analyzeVideo(url, onProgress) {
522
542
  let source_title = '';
523
543
  try {
524
544
  const t = await run(YT_DLP, ['--skip-download', '--no-warnings', '--no-playlist', '--user-agent', SRC_UA, ...cookieArgs(), '--print', '%(title)s', url]);
525
- source_title = (t.out || '').trim().split('\n')[0].slice(0, 200);
545
+ source_title = cleanSourceTitle(t.out);
526
546
  }
527
547
  catch { /* title is best-effort — analysis still proceeds without it */ }
528
548
  progress('Đang tách audio...');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tuna-agent",
3
- "version": "0.1.156",
3
+ "version": "0.1.157",
4
4
  "description": "Tuna Agent - Run AI coding tasks on your machine",
5
5
  "bin": {
6
6
  "tuna-agent": "dist/cli/index.js"