@kimjansheden/payload-video-processor 0.1.2 → 0.1.3
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/dist/admin/VideoField.d.cts +1 -1
- package/dist/admin/VideoField.d.ts +1 -1
- package/dist/admin/client.d.cts +1 -1
- package/dist/admin/client.d.ts +1 -1
- package/dist/index.cjs +191 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +191 -1
- package/dist/index.js.map +1 -1
- package/dist/{types-BjFcE25o.d.cts → types-DJGPSfvi.d.cts} +6 -1
- package/dist/{types-BjFcE25o.d.ts → types-DJGPSfvi.d.ts} +6 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -637,6 +637,166 @@ var createReplaceOriginalHandler = ({ access }) => async (req) => {
|
|
|
637
637
|
}
|
|
638
638
|
};
|
|
639
639
|
|
|
640
|
+
// src/utils/playback.ts
|
|
641
|
+
var isAbsoluteUrl = (value) => value.startsWith("http://") || value.startsWith("https://") || value.startsWith("data:") || value.startsWith("blob:") || value.startsWith("//");
|
|
642
|
+
var readHeader = (headers, name) => {
|
|
643
|
+
if (!headers) {
|
|
644
|
+
return "";
|
|
645
|
+
}
|
|
646
|
+
if (typeof headers.get === "function") {
|
|
647
|
+
return headers.get(name) ?? headers.get(name.toLowerCase()) ?? "";
|
|
648
|
+
}
|
|
649
|
+
const record = headers;
|
|
650
|
+
const value = record[name] ?? record[name.toLowerCase()];
|
|
651
|
+
if (typeof value === "string") {
|
|
652
|
+
return value;
|
|
653
|
+
}
|
|
654
|
+
if (Array.isArray(value)) {
|
|
655
|
+
return typeof value[0] === "string" ? value[0] : "";
|
|
656
|
+
}
|
|
657
|
+
return "";
|
|
658
|
+
};
|
|
659
|
+
var getServerUrlFromReq = (req) => {
|
|
660
|
+
const serverURL = req?.payload?.config?.serverURL;
|
|
661
|
+
return typeof serverURL === "string" ? serverURL.trim() : "";
|
|
662
|
+
};
|
|
663
|
+
var getRequestOrigin = (req) => {
|
|
664
|
+
const serverURL = getServerUrlFromReq(req);
|
|
665
|
+
if (serverURL) {
|
|
666
|
+
try {
|
|
667
|
+
return new URL(serverURL).origin;
|
|
668
|
+
} catch {
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
const requestUrl = typeof req?.url === "string" ? req.url : "";
|
|
672
|
+
if (requestUrl && isAbsoluteUrl(requestUrl)) {
|
|
673
|
+
try {
|
|
674
|
+
return new URL(requestUrl).origin;
|
|
675
|
+
} catch {
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
const headers = req?.headers;
|
|
679
|
+
const forwardedProto = readHeader(headers, "x-forwarded-proto");
|
|
680
|
+
const forwardedHost = readHeader(headers, "x-forwarded-host");
|
|
681
|
+
const host = forwardedHost || readHeader(headers, "host");
|
|
682
|
+
const proto = forwardedProto || "http";
|
|
683
|
+
return host ? `${proto}://${host}` : "";
|
|
684
|
+
};
|
|
685
|
+
var resolvePlaybackUrl = (input, bases) => {
|
|
686
|
+
if (typeof input !== "string") {
|
|
687
|
+
return "";
|
|
688
|
+
}
|
|
689
|
+
const trimmed = input.trim();
|
|
690
|
+
if (!trimmed) {
|
|
691
|
+
return "";
|
|
692
|
+
}
|
|
693
|
+
if (isAbsoluteUrl(trimmed)) {
|
|
694
|
+
try {
|
|
695
|
+
return new URL(trimmed).toString();
|
|
696
|
+
} catch {
|
|
697
|
+
return "";
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
for (const base of bases) {
|
|
701
|
+
if (!base) {
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
try {
|
|
705
|
+
return new URL(trimmed, base).toString();
|
|
706
|
+
} catch {
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
return trimmed;
|
|
710
|
+
};
|
|
711
|
+
var inferVideoMimeTypeFromUrl = (url) => {
|
|
712
|
+
const cleanUrl = url.split("#")[0]?.split("?")[0] ?? "";
|
|
713
|
+
const lower = cleanUrl.toLowerCase();
|
|
714
|
+
if (lower.endsWith(".mp4") || lower.endsWith(".m4v") || lower.endsWith(".mov")) {
|
|
715
|
+
return "video/mp4";
|
|
716
|
+
}
|
|
717
|
+
if (lower.endsWith(".webm")) {
|
|
718
|
+
return "video/webm";
|
|
719
|
+
}
|
|
720
|
+
if (lower.endsWith(".ogv") || lower.endsWith(".ogg")) {
|
|
721
|
+
return "video/ogg";
|
|
722
|
+
}
|
|
723
|
+
return void 0;
|
|
724
|
+
};
|
|
725
|
+
var normaliseVideoSourceType = (mimeType, resolvedUrl) => {
|
|
726
|
+
const normalised = typeof mimeType === "string" ? mimeType.trim().toLowerCase() : "";
|
|
727
|
+
if (normalised === "video/quicktime") {
|
|
728
|
+
return "video/mp4";
|
|
729
|
+
}
|
|
730
|
+
if (normalised) {
|
|
731
|
+
return normalised;
|
|
732
|
+
}
|
|
733
|
+
return inferVideoMimeTypeFromUrl(resolvedUrl);
|
|
734
|
+
};
|
|
735
|
+
var getThumbnailCandidate = (doc) => {
|
|
736
|
+
const sizes = doc.sizes;
|
|
737
|
+
if (sizes && typeof sizes === "object") {
|
|
738
|
+
const sizeCandidates = ["medium", "large", "square", "thumbnail"];
|
|
739
|
+
for (const key of sizeCandidates) {
|
|
740
|
+
const entry = sizes[key];
|
|
741
|
+
const url = entry?.url;
|
|
742
|
+
if (typeof url === "string" && url.trim()) {
|
|
743
|
+
return url;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
if (typeof doc.thumbnailURL === "string" && doc.thumbnailURL.trim()) {
|
|
748
|
+
return doc.thumbnailURL;
|
|
749
|
+
}
|
|
750
|
+
return void 0;
|
|
751
|
+
};
|
|
752
|
+
var buildPlaybackSources = ({
|
|
753
|
+
doc,
|
|
754
|
+
req
|
|
755
|
+
}) => {
|
|
756
|
+
const sources = [];
|
|
757
|
+
const seen = /* @__PURE__ */ new Set();
|
|
758
|
+
const docUrl = typeof doc.url === "string" ? doc.url.trim() : "";
|
|
759
|
+
const requestOrigin = getRequestOrigin(req);
|
|
760
|
+
const bases = [docUrl, requestOrigin].filter(Boolean);
|
|
761
|
+
const variants = Array.isArray(doc.variants) ? doc.variants : [];
|
|
762
|
+
const sortedVariants = [...variants].sort((a, b) => {
|
|
763
|
+
const aSize = typeof a?.size === "number" ? a.size : Number.NEGATIVE_INFINITY;
|
|
764
|
+
const bSize = typeof b?.size === "number" ? b.size : Number.NEGATIVE_INFINITY;
|
|
765
|
+
return bSize - aSize;
|
|
766
|
+
});
|
|
767
|
+
for (const variant of sortedVariants) {
|
|
768
|
+
const resolvedUrl = resolvePlaybackUrl(variant?.url, bases);
|
|
769
|
+
if (!resolvedUrl || seen.has(resolvedUrl)) {
|
|
770
|
+
continue;
|
|
771
|
+
}
|
|
772
|
+
seen.add(resolvedUrl);
|
|
773
|
+
sources.push({
|
|
774
|
+
preset: typeof variant?.preset === "string" ? variant.preset : void 0,
|
|
775
|
+
src: resolvedUrl,
|
|
776
|
+
type: normaliseVideoSourceType(void 0, resolvedUrl)
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
const resolvedOriginalUrl = resolvePlaybackUrl(doc.url, bases);
|
|
780
|
+
if (resolvedOriginalUrl && !seen.has(resolvedOriginalUrl)) {
|
|
781
|
+
sources.push({
|
|
782
|
+
src: resolvedOriginalUrl,
|
|
783
|
+
type: normaliseVideoSourceType(doc.mimeType, resolvedOriginalUrl)
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
return sources;
|
|
787
|
+
};
|
|
788
|
+
var buildPlaybackPosterUrl = ({
|
|
789
|
+
doc,
|
|
790
|
+
req
|
|
791
|
+
}) => {
|
|
792
|
+
const docUrl = typeof doc.url === "string" ? doc.url.trim() : "";
|
|
793
|
+
const requestOrigin = getRequestOrigin(req);
|
|
794
|
+
const bases = [docUrl, requestOrigin].filter(Boolean);
|
|
795
|
+
const candidate = getThumbnailCandidate(doc);
|
|
796
|
+
const resolved = resolvePlaybackUrl(candidate, bases);
|
|
797
|
+
return resolved || void 0;
|
|
798
|
+
};
|
|
799
|
+
|
|
640
800
|
// src/ffmpeg/args.ts
|
|
641
801
|
var FASTSTART_FLAGS = ["-movflags", "+faststart"];
|
|
642
802
|
var CRF_FLAG = "-crf";
|
|
@@ -1077,9 +1237,39 @@ var pluginFactory = (rawOptions) => {
|
|
|
1077
1237
|
};
|
|
1078
1238
|
fields.push(controlField);
|
|
1079
1239
|
}
|
|
1240
|
+
const existingHooks = collection.hooks ?? {};
|
|
1241
|
+
const existingAfterRead = Array.isArray(existingHooks.afterRead) ? existingHooks.afterRead : [];
|
|
1242
|
+
const hooks = {
|
|
1243
|
+
...existingHooks,
|
|
1244
|
+
afterRead: [
|
|
1245
|
+
...existingAfterRead,
|
|
1246
|
+
({ doc, req }) => {
|
|
1247
|
+
if (!doc || typeof doc !== "object") {
|
|
1248
|
+
return doc;
|
|
1249
|
+
}
|
|
1250
|
+
const mimeType = typeof doc.mimeType === "string" ? doc.mimeType : "";
|
|
1251
|
+
if (!mimeType.startsWith("video/")) {
|
|
1252
|
+
return doc;
|
|
1253
|
+
}
|
|
1254
|
+
doc.playbackSources = buildPlaybackSources({
|
|
1255
|
+
doc,
|
|
1256
|
+
req
|
|
1257
|
+
});
|
|
1258
|
+
const posterUrl = buildPlaybackPosterUrl({
|
|
1259
|
+
doc,
|
|
1260
|
+
req
|
|
1261
|
+
});
|
|
1262
|
+
if (posterUrl) {
|
|
1263
|
+
doc.playbackPosterUrl = posterUrl;
|
|
1264
|
+
}
|
|
1265
|
+
return doc;
|
|
1266
|
+
}
|
|
1267
|
+
]
|
|
1268
|
+
};
|
|
1080
1269
|
return {
|
|
1081
1270
|
...collection,
|
|
1082
|
-
fields
|
|
1271
|
+
fields,
|
|
1272
|
+
hooks
|
|
1083
1273
|
};
|
|
1084
1274
|
}
|
|
1085
1275
|
);
|