fluncle 0.75.0 → 0.76.0

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.
Files changed (2) hide show
  1. package/bin/fluncle.mjs +57 -12
  2. package/package.json +1 -1
package/bin/fluncle.mjs CHANGED
@@ -462,6 +462,26 @@ function versionMatches(findingTitle, candidateTitle) {
462
462
  }
463
463
  return !candidateIsRemix;
464
464
  }
465
+ function trackLabel(artists, title) {
466
+ const joined = artists.join(", ");
467
+ return joined && title ? `${joined} — ${title}` : joined || title;
468
+ }
469
+ function resolveClipTracks(options) {
470
+ const { inMs, members, outMs, setDurationMs } = options;
471
+ const cued = members.filter((member) => member.startMs != null).sort((a, b) => a.startMs - b.startMs);
472
+ if (cued.length === 0) {
473
+ return [];
474
+ }
475
+ const lastIndex = cued.length - 1;
476
+ return cued.filter((member, index) => {
477
+ const lo = index === 0 ? Math.min(member.startMs, inMs) : member.startMs;
478
+ const hi = index === lastIndex ? Math.max(setDurationMs, outMs) : cued[index + 1]?.startMs ?? Number.POSITIVE_INFINITY;
479
+ return lo < outMs && inMs < hi;
480
+ }).map((member) => ({
481
+ label: trackLabel(member.artists, member.title),
482
+ startMs: member.startMs
483
+ }));
484
+ }
465
485
  function baseTitleMatches(findingTitle, candidateTitle) {
466
486
  const want = new Set(tokenize(stripVersionSuffix(findingTitle)));
467
487
  const have = new Set(tokenize(stripVersionSuffix(candidateTitle)));
@@ -524,7 +544,7 @@ function parseVersion(version) {
524
544
  var currentVersion;
525
545
  var init_version = __esm(() => {
526
546
  init_output();
527
- currentVersion = "0.75.0".trim() ? "0.75.0".trim() : "0.1.0";
547
+ currentVersion = "0.76.0".trim() ? "0.76.0".trim() : "0.1.0";
528
548
  });
529
549
 
530
550
  // src/update-notifier.ts
@@ -2381,7 +2401,7 @@ function parseVersion2(version) {
2381
2401
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
2382
2402
  var init_version2 = __esm(() => {
2383
2403
  init_output();
2384
- currentVersion2 = "0.75.0".trim() ? "0.75.0".trim() : "0.1.0";
2404
+ currentVersion2 = "0.76.0".trim() ? "0.76.0".trim() : "0.1.0";
2385
2405
  });
2386
2406
 
2387
2407
  // ../../packages/registry/src/index.ts
@@ -4035,20 +4055,42 @@ function brandDrawtext(options) {
4035
4055
  const value = escapeDrawtextValue(options.text);
4036
4056
  const font = options.fontFile ? `:fontfile='${options.fontFile}'` : "";
4037
4057
  const border = options.borderw && options.borderw > 0 ? `:borderw=${options.borderw}:bordercolor=${CLIP_HALO_COLOR}` : "";
4038
- return `drawtext=text='${value}'${font}:` + `fontcolor=${options.color}:fontsize=${options.size}:` + `x=${options.x}:y=${options.y}${border}`;
4058
+ const enable = options.enable ? `:enable='${options.enable}'` : "";
4059
+ return `drawtext=text='${value}'${font}:` + `fontcolor=${options.color}:fontsize=${options.size}:` + `x=${options.x}:y=${options.y}${border}${enable}`;
4060
+ }
4061
+ function resolveTitleLines(options, y) {
4062
+ const inMs = options.inMs ?? 0;
4063
+ const outMs = options.outMs ?? 0;
4064
+ const clipDur = Math.max(0, (outMs - inMs) / 1000);
4065
+ const base = { fontFile: options.sansFontFile, size: CLIP_TITLE_SIZE, x: CLIP_MARGIN_X, y };
4066
+ const resolved = options.members && options.members.length > 0 ? resolveClipTracks({
4067
+ inMs,
4068
+ members: options.members,
4069
+ outMs,
4070
+ setDurationMs: options.setDurationMs ?? 0
4071
+ }) : [];
4072
+ if (resolved.length === 0) {
4073
+ return [{ ...base, text: options.title }];
4074
+ }
4075
+ const clamp = (seconds) => Math.min(Math.max(seconds, 0), clipDur);
4076
+ return resolved.map((track, index) => {
4077
+ const relStart = clamp((track.startMs - inMs) / 1000);
4078
+ const next = resolved[index + 1];
4079
+ const relEnd = next ? clamp((next.startMs - inMs) / 1000) : clipDur;
4080
+ return {
4081
+ ...base,
4082
+ enable: `between(t,${relStart.toFixed(3)},${relEnd.toFixed(3)})`,
4083
+ text: track.label
4084
+ };
4085
+ });
4039
4086
  }
4040
4087
  function clipCutFilterComplex(options) {
4041
4088
  const xOffset = Math.max(0, Math.round(options.xOffset));
4042
4089
  const crop = `crop=ih*9/16:ih:${xOffset}:0,scale=${CLIP_WIDTH}:${CLIP_HEIGHT}`;
4043
4090
  const coordinateBox = Math.round(CLIP_COORDINATE_SIZE * 1.18);
4044
4091
  const titleBottomOffset = CLIP_SAFE_BOTTOM + coordinateBox + CLIP_LINE_GAP;
4045
- const title = {
4046
- fontFile: options.sansFontFile,
4047
- size: CLIP_TITLE_SIZE,
4048
- text: options.title,
4049
- x: CLIP_MARGIN_X,
4050
- y: `h-${titleBottomOffset}-th`
4051
- };
4092
+ const titleY = `h-${titleBottomOffset}-th`;
4093
+ const titleLines = resolveTitleLines(options, titleY);
4052
4094
  const coordinate2 = {
4053
4095
  fontFile: options.oxaniumFontFile,
4054
4096
  size: CLIP_COORDINATE_SIZE,
@@ -4057,11 +4099,11 @@ function clipCutFilterComplex(options) {
4057
4099
  y: `h-${CLIP_SAFE_BOTTOM}-th`
4058
4100
  };
4059
4101
  const haloGlyphs = [
4060
- brandDrawtext({ ...title, color: CLIP_HALO_COLOR }),
4102
+ ...titleLines.map((line) => brandDrawtext({ ...line, color: CLIP_HALO_COLOR })),
4061
4103
  brandDrawtext({ ...coordinate2, color: CLIP_HALO_COLOR })
4062
4104
  ].join(",");
4063
4105
  const sharpGlyphs = [
4064
- brandDrawtext({ ...title, borderw: CLIP_SHARP_BORDERW, color: CLIP_TITLE_COLOR }),
4106
+ ...titleLines.map((line) => brandDrawtext({ ...line, borderw: CLIP_SHARP_BORDERW, color: CLIP_TITLE_COLOR })),
4065
4107
  brandDrawtext({ ...coordinate2, borderw: CLIP_SHARP_BORDERW, color: CLIP_COORDINATE_COLOR })
4066
4108
  ].join(",");
4067
4109
  return [
@@ -4148,10 +4190,12 @@ async function clipCutCommand(clipId, onProgress = () => {}) {
4148
4190
  await runClipCut({
4149
4191
  inMs: clip.inMs,
4150
4192
  logId: mixtape.logId,
4193
+ members: mixtape.members,
4151
4194
  outMs: clip.outMs,
4152
4195
  outputPath,
4153
4196
  oxaniumFontFile: resolveClipFontFile(),
4154
4197
  sansFontFile: resolveClipSansFontFile(),
4198
+ setDurationMs: mixtape.durationMs ?? 0,
4155
4199
  setUrl,
4156
4200
  title: mixtape.title,
4157
4201
  xOffset: clip.xOffset
@@ -4214,6 +4258,7 @@ async function runClipCut(options) {
4214
4258
  }
4215
4259
  var FOUND_BASE3 = "https://found.fluncle.com", CLIP_WIDTH = 1080, CLIP_HEIGHT = 1920, CLIP_CRF = 21, CLIP_MAXRATE = "10M", CLIP_BUFSIZE = "20M", CLIP_AUDIO_BITRATE = "192k", MAX_CLIP_BYTES, CLIP_TITLE_COLOR = "0xf4ead7", CLIP_COORDINATE_COLOR = "0xb7ab95", CLIP_HALO_COLOR = "0x090a0b", CLIP_HALO_CORE_SIGMA = 3, CLIP_HALO_FEATHER_SIGMA = 9, CLIP_SHARP_BORDERW = 1, CLIP_MARGIN_X = 96, CLIP_SAFE_BOTTOM = 230, CLIP_LINE_GAP = 10, CLIP_TITLE_SIZE = 40, CLIP_COORDINATE_SIZE = 22, BOX_CLIP_FONT_FILE = "/opt/fonts/Oxanium-SemiBold.ttf", BOX_CLIP_SANS_FONT_FILE = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf";
4216
4260
  var init_clips = __esm(() => {
4261
+ init_util();
4217
4262
  init_api();
4218
4263
  init_output();
4219
4264
  MAX_CLIP_BYTES = 100 * 1024 * 1024;
package/package.json CHANGED
@@ -31,5 +31,5 @@
31
31
  "url": "git+https://github.com/mauricekleine/fluncle.git"
32
32
  },
33
33
  "type": "module",
34
- "version": "0.75.0"
34
+ "version": "0.76.0"
35
35
  }