@shumai-one/shumai-transcode 0.3.3 → 0.3.4
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/{chunk-nt1573w8.js → chunk-ehbk2rm4.js} +139 -27
- package/bin/shumai-transcode-app.js +156 -41
- package/package.json +7 -7
- package/prisma/migrations/20260806082136_add_sharelink_watermark/migration.sql +69 -0
- package/prisma/migrations/20260806085643_add_watermark_file_status/migration.sql +7 -0
- package/prisma/migrations/20260807140837_clean_media_remove_raw_transcodes_and_original_download_url/migration.sql +86 -0
- package/prisma/migrations/20260808014542_add_sharelink_allow_download/migration.sql +2 -0
- package/prisma/schema.prisma +68 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shumai-one/shumai-transcode",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "Media transcoding worker for the shumai media workspace",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"zod": "4.4.3"
|
|
28
28
|
},
|
|
29
29
|
"optionalDependencies": {
|
|
30
|
-
"@shumai-one/shumai-transcode-darwin-arm64": "0.3.
|
|
31
|
-
"@shumai-one/shumai-transcode-darwin-x64": "0.3.
|
|
32
|
-
"@shumai-one/shumai-transcode-linux-arm64": "0.3.
|
|
33
|
-
"@shumai-one/shumai-transcode-linux-x64": "0.3.
|
|
34
|
-
"@shumai-one/shumai-transcode-win32-arm64": "0.3.
|
|
35
|
-
"@shumai-one/shumai-transcode-win32-x64": "0.3.
|
|
30
|
+
"@shumai-one/shumai-transcode-darwin-arm64": "0.3.4",
|
|
31
|
+
"@shumai-one/shumai-transcode-darwin-x64": "0.3.4",
|
|
32
|
+
"@shumai-one/shumai-transcode-linux-arm64": "0.3.4",
|
|
33
|
+
"@shumai-one/shumai-transcode-linux-x64": "0.3.4",
|
|
34
|
+
"@shumai-one/shumai-transcode-win32-arm64": "0.3.4",
|
|
35
|
+
"@shumai-one/shumai-transcode-win32-x64": "0.3.4"
|
|
36
36
|
},
|
|
37
37
|
"repository": {
|
|
38
38
|
"type": "git",
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
-- CreateEnum
|
|
2
|
+
CREATE TYPE "WatermarkStatus" AS ENUM ('disabled', 'processing', 'ready', 'failed');
|
|
3
|
+
|
|
4
|
+
-- AlterEnum
|
|
5
|
+
ALTER TYPE "WorkflowTaskType" ADD VALUE 'transcode_watermark';
|
|
6
|
+
|
|
7
|
+
-- AlterTable
|
|
8
|
+
ALTER TABLE "share_links" ADD COLUMN "watermark_config_id" TEXT,
|
|
9
|
+
ADD COLUMN "watermark_status" "WatermarkStatus" NOT NULL DEFAULT 'disabled';
|
|
10
|
+
|
|
11
|
+
-- CreateTable
|
|
12
|
+
CREATE TABLE "watermark_configs" (
|
|
13
|
+
"id" TEXT NOT NULL,
|
|
14
|
+
"config" JSONB NOT NULL,
|
|
15
|
+
"hash" TEXT NOT NULL,
|
|
16
|
+
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
17
|
+
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
18
|
+
|
|
19
|
+
CONSTRAINT "watermark_configs_pkey" PRIMARY KEY ("id")
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
-- CreateTable
|
|
23
|
+
CREATE TABLE "watermark_templates" (
|
|
24
|
+
"id" TEXT NOT NULL,
|
|
25
|
+
"name" TEXT NOT NULL,
|
|
26
|
+
"config" JSONB NOT NULL,
|
|
27
|
+
"team_id" TEXT,
|
|
28
|
+
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
29
|
+
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
30
|
+
|
|
31
|
+
CONSTRAINT "watermark_templates_pkey" PRIMARY KEY ("id")
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
-- CreateTable
|
|
35
|
+
CREATE TABLE "watermark_files" (
|
|
36
|
+
"id" TEXT NOT NULL,
|
|
37
|
+
"asset_id" TEXT NOT NULL,
|
|
38
|
+
"watermark_config_id" TEXT NOT NULL,
|
|
39
|
+
"media" JSONB,
|
|
40
|
+
"status" "WorkflowTaskStatus" NOT NULL DEFAULT 'pending',
|
|
41
|
+
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
42
|
+
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
43
|
+
|
|
44
|
+
CONSTRAINT "watermark_files_pkey" PRIMARY KEY ("id")
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
-- CreateIndex
|
|
48
|
+
CREATE UNIQUE INDEX "watermark_configs_hash_key" ON "watermark_configs"("hash");
|
|
49
|
+
|
|
50
|
+
-- CreateIndex
|
|
51
|
+
CREATE INDEX "watermark_templates_team_id_idx" ON "watermark_templates"("team_id");
|
|
52
|
+
|
|
53
|
+
-- CreateIndex
|
|
54
|
+
CREATE INDEX "watermark_files_watermark_config_id_idx" ON "watermark_files"("watermark_config_id");
|
|
55
|
+
|
|
56
|
+
-- CreateIndex
|
|
57
|
+
CREATE UNIQUE INDEX "watermark_files_asset_id_watermark_config_id_key" ON "watermark_files"("asset_id", "watermark_config_id");
|
|
58
|
+
|
|
59
|
+
-- AddForeignKey
|
|
60
|
+
ALTER TABLE "share_links" ADD CONSTRAINT "share_links_watermark_config_id_fkey" FOREIGN KEY ("watermark_config_id") REFERENCES "watermark_configs"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
61
|
+
|
|
62
|
+
-- AddForeignKey
|
|
63
|
+
ALTER TABLE "watermark_templates" ADD CONSTRAINT "watermark_templates_team_id_fkey" FOREIGN KEY ("team_id") REFERENCES "teams"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
64
|
+
|
|
65
|
+
-- AddForeignKey
|
|
66
|
+
ALTER TABLE "watermark_files" ADD CONSTRAINT "watermark_files_asset_id_fkey" FOREIGN KEY ("asset_id") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
67
|
+
|
|
68
|
+
-- AddForeignKey
|
|
69
|
+
ALTER TABLE "watermark_files" ADD CONSTRAINT "watermark_files_watermark_config_id_fkey" FOREIGN KEY ("watermark_config_id") REFERENCES "watermark_configs"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-- CreateEnum
|
|
2
|
+
CREATE TYPE "WatermarkFileStatus" AS ENUM ('pending', 'processing', 'completed', 'failed');
|
|
3
|
+
|
|
4
|
+
-- AlterTable
|
|
5
|
+
ALTER TABLE "watermark_files" ALTER COLUMN "status" DROP DEFAULT;
|
|
6
|
+
ALTER TABLE "watermark_files" ALTER COLUMN "status" TYPE "WatermarkFileStatus" USING ("status"::text::"WatermarkFileStatus");
|
|
7
|
+
ALTER TABLE "watermark_files" ALTER COLUMN "status" SET DEFAULT 'pending';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
-- Data cleanup: remove legacy media JSON fields that are no longer used.
|
|
2
|
+
--
|
|
3
|
+
-- WebUI now displays transcoded proxies only and never falls back to the raw
|
|
4
|
+
-- original file:
|
|
5
|
+
-- 1. Drop the raw-original marker entries (`isRaw: true`) from
|
|
6
|
+
-- videoTranscodes / imageTranscodes. They pointed at the original file
|
|
7
|
+
-- key and were only consumed by the removed display fallbacks and the
|
|
8
|
+
-- download-menu entries, which now use media.original.key directly.
|
|
9
|
+
-- 2. Strip the now-removed `isRaw` field from remaining transcode entries.
|
|
10
|
+
-- 3. Drop `original.downloadUrl` (removed from the AssetInfo DTO; downloads
|
|
11
|
+
-- resolve a fresh presigned URL from `key` via the download-url APIs).
|
|
12
|
+
|
|
13
|
+
UPDATE "assets"
|
|
14
|
+
SET "media" = jsonb_set(
|
|
15
|
+
jsonb_set(
|
|
16
|
+
CASE WHEN jsonb_typeof("media"->'original') = 'object'
|
|
17
|
+
THEN "media" #- '{original,downloadUrl}'
|
|
18
|
+
ELSE "media" END,
|
|
19
|
+
'{videoTranscodes}',
|
|
20
|
+
COALESCE(
|
|
21
|
+
(SELECT jsonb_agg(elem - 'isRaw')
|
|
22
|
+
FROM jsonb_array_elements("media"->'videoTranscodes') elem
|
|
23
|
+
WHERE jsonb_typeof(elem) = 'object'
|
|
24
|
+
AND NOT COALESCE((elem->>'isRaw')::boolean, false)),
|
|
25
|
+
'[]'::jsonb
|
|
26
|
+
)
|
|
27
|
+
),
|
|
28
|
+
'{imageTranscodes}',
|
|
29
|
+
COALESCE(
|
|
30
|
+
(SELECT jsonb_agg(elem - 'isRaw')
|
|
31
|
+
FROM jsonb_array_elements("media"->'imageTranscodes') elem
|
|
32
|
+
WHERE jsonb_typeof(elem) = 'object'
|
|
33
|
+
AND NOT COALESCE((elem->>'isRaw')::boolean, false)),
|
|
34
|
+
'[]'::jsonb
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
WHERE "media" IS NOT NULL
|
|
38
|
+
AND (
|
|
39
|
+
(jsonb_typeof("media"->'original') = 'object' AND "media"->'original' ? 'downloadUrl')
|
|
40
|
+
OR EXISTS (
|
|
41
|
+
SELECT 1 FROM jsonb_array_elements(COALESCE("media"->'videoTranscodes', '[]'::jsonb)) e
|
|
42
|
+
WHERE jsonb_typeof(e) = 'object' AND e ? 'isRaw'
|
|
43
|
+
)
|
|
44
|
+
OR EXISTS (
|
|
45
|
+
SELECT 1 FROM jsonb_array_elements(COALESCE("media"->'imageTranscodes', '[]'::jsonb)) e
|
|
46
|
+
WHERE jsonb_typeof(e) = 'object' AND e ? 'isRaw'
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
-- Same cleanup for watermarked proxy media.
|
|
51
|
+
UPDATE "watermark_files"
|
|
52
|
+
SET "media" = jsonb_set(
|
|
53
|
+
jsonb_set(
|
|
54
|
+
CASE WHEN jsonb_typeof("media"->'original') = 'object'
|
|
55
|
+
THEN "media" #- '{original,downloadUrl}'
|
|
56
|
+
ELSE "media" END,
|
|
57
|
+
'{videoTranscodes}',
|
|
58
|
+
COALESCE(
|
|
59
|
+
(SELECT jsonb_agg(elem - 'isRaw')
|
|
60
|
+
FROM jsonb_array_elements("media"->'videoTranscodes') elem
|
|
61
|
+
WHERE jsonb_typeof(elem) = 'object'
|
|
62
|
+
AND NOT COALESCE((elem->>'isRaw')::boolean, false)),
|
|
63
|
+
'[]'::jsonb
|
|
64
|
+
)
|
|
65
|
+
),
|
|
66
|
+
'{imageTranscodes}',
|
|
67
|
+
COALESCE(
|
|
68
|
+
(SELECT jsonb_agg(elem - 'isRaw')
|
|
69
|
+
FROM jsonb_array_elements("media"->'imageTranscodes') elem
|
|
70
|
+
WHERE jsonb_typeof(elem) = 'object'
|
|
71
|
+
AND NOT COALESCE((elem->>'isRaw')::boolean, false)),
|
|
72
|
+
'[]'::jsonb
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
WHERE "media" IS NOT NULL
|
|
76
|
+
AND (
|
|
77
|
+
(jsonb_typeof("media"->'original') = 'object' AND "media"->'original' ? 'downloadUrl')
|
|
78
|
+
OR EXISTS (
|
|
79
|
+
SELECT 1 FROM jsonb_array_elements(COALESCE("media"->'videoTranscodes', '[]'::jsonb)) e
|
|
80
|
+
WHERE jsonb_typeof(e) = 'object' AND e ? 'isRaw'
|
|
81
|
+
)
|
|
82
|
+
OR EXISTS (
|
|
83
|
+
SELECT 1 FROM jsonb_array_elements(COALESCE("media"->'imageTranscodes', '[]'::jsonb)) e
|
|
84
|
+
WHERE jsonb_typeof(e) = 'object' AND e ? 'isRaw'
|
|
85
|
+
)
|
|
86
|
+
);
|
package/prisma/schema.prisma
CHANGED
|
@@ -106,6 +106,7 @@ enum WorkflowTaskType {
|
|
|
106
106
|
transcode_pdf_pages
|
|
107
107
|
transcode_screenshot
|
|
108
108
|
transcode_image_annotation
|
|
109
|
+
transcode_watermark
|
|
109
110
|
ai_metadata_autofill
|
|
110
111
|
chat
|
|
111
112
|
ai_embedding
|
|
@@ -120,6 +121,20 @@ enum WorkflowTaskStatus {
|
|
|
120
121
|
failed
|
|
121
122
|
}
|
|
122
123
|
|
|
124
|
+
enum WatermarkStatus {
|
|
125
|
+
disabled
|
|
126
|
+
processing
|
|
127
|
+
ready
|
|
128
|
+
failed
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
enum WatermarkFileStatus {
|
|
132
|
+
pending
|
|
133
|
+
processing
|
|
134
|
+
completed
|
|
135
|
+
failed
|
|
136
|
+
}
|
|
137
|
+
|
|
123
138
|
// ----------------------------------------------------------------------
|
|
124
139
|
// Models
|
|
125
140
|
// ----------------------------------------------------------------------
|
|
@@ -241,6 +256,7 @@ model Team {
|
|
|
241
256
|
agents Agent[] @relation("TeamToAgent")
|
|
242
257
|
aiUsages AiUsage[] @relation("TeamToAiUsage")
|
|
243
258
|
auditLogs AuditLog[] @relation("TeamToAuditLog")
|
|
259
|
+
watermarkTemplates WatermarkTemplate[] @relation("TeamToWatermarkTemplate")
|
|
244
260
|
|
|
245
261
|
@@map("teams")
|
|
246
262
|
}
|
|
@@ -351,6 +367,7 @@ model ShareLink {
|
|
|
351
367
|
expireAt DateTime? @map("expire_at")
|
|
352
368
|
password String?
|
|
353
369
|
isDisabled Boolean @default(false) @map("is_disabled")
|
|
370
|
+
allowDownload Boolean @default(true) @map("allow_download")
|
|
354
371
|
defaultSortOrder String? @map("default_sort_order")
|
|
355
372
|
viewMode String? @map("view_mode")
|
|
356
373
|
/// [ShareLinkFieldVisibility]
|
|
@@ -367,9 +384,59 @@ model ShareLink {
|
|
|
367
384
|
creatorId String? @map("creator_id")
|
|
368
385
|
creator User? @relation("UserToShareLink", fields: [creatorId], references: [id])
|
|
369
386
|
|
|
387
|
+
watermarkConfigId String? @map("watermark_config_id")
|
|
388
|
+
watermarkStatus WatermarkStatus @default(disabled) @map("watermark_status")
|
|
389
|
+
watermarkConfig WatermarkConfig? @relation(fields: [watermarkConfigId], references: [id], onDelete: SetNull)
|
|
390
|
+
|
|
370
391
|
@@map("share_links")
|
|
371
392
|
}
|
|
372
393
|
|
|
394
|
+
model WatermarkConfig {
|
|
395
|
+
id String @id @default(ulid())
|
|
396
|
+
/// [WatermarkConfigSpec]
|
|
397
|
+
config Json
|
|
398
|
+
hash String @unique
|
|
399
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
400
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
401
|
+
|
|
402
|
+
shareLinks ShareLink[]
|
|
403
|
+
watermarkFiles WatermarkFile[]
|
|
404
|
+
|
|
405
|
+
@@map("watermark_configs")
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
model WatermarkTemplate {
|
|
409
|
+
id String @id @default(ulid())
|
|
410
|
+
name String
|
|
411
|
+
/// [WatermarkConfigSpec]
|
|
412
|
+
config Json
|
|
413
|
+
teamId String? @map("team_id")
|
|
414
|
+
team Team? @relation("TeamToWatermarkTemplate", fields: [teamId], references: [id], onDelete: Cascade)
|
|
415
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
416
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
417
|
+
|
|
418
|
+
@@index([teamId])
|
|
419
|
+
@@map("watermark_templates")
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
model WatermarkFile {
|
|
423
|
+
id String @id @default(ulid())
|
|
424
|
+
assetId String @map("asset_id")
|
|
425
|
+
watermarkConfigId String @map("watermark_config_id")
|
|
426
|
+
/// [MediaInfo]
|
|
427
|
+
media Json?
|
|
428
|
+
status WatermarkFileStatus @default(pending)
|
|
429
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
430
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
431
|
+
|
|
432
|
+
asset Asset @relation("AssetToWatermarkFile", fields: [assetId], references: [id], onDelete: Cascade)
|
|
433
|
+
watermarkConfig WatermarkConfig @relation(fields: [watermarkConfigId], references: [id], onDelete: Cascade)
|
|
434
|
+
|
|
435
|
+
@@unique([assetId, watermarkConfigId])
|
|
436
|
+
@@index([watermarkConfigId])
|
|
437
|
+
@@map("watermark_files")
|
|
438
|
+
}
|
|
439
|
+
|
|
373
440
|
model Asset {
|
|
374
441
|
id String @id @default(ulid())
|
|
375
442
|
name String @default("")
|
|
@@ -421,6 +488,7 @@ model Asset {
|
|
|
421
488
|
projectShareRoot Project? @relation("ProjectToShareRoot")
|
|
422
489
|
shareLinkRootFolder ShareLink? @relation("ShareLinkToRootFolder")
|
|
423
490
|
agentSessions AgentSession[] @relation("AssetToAgentSession")
|
|
491
|
+
watermarkFiles WatermarkFile[] @relation("AssetToWatermarkFile")
|
|
424
492
|
|
|
425
493
|
@@map("assets")
|
|
426
494
|
@@index([type])
|