@ttt-productions/moderation-core 0.8.1 → 0.8.2
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/server/index.d.ts +2 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/video-moderation.d.ts +13 -0
- package/dist/server/video-moderation.d.ts.map +1 -1
- package/dist/server/video-moderation.js +17 -0
- package/dist/server/video-moderation.js.map +1 -1
- package/package.json +1 -1
package/dist/server/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { moderateImage, __resetDefaultVisionClient, } from "./image-moderation.js";
|
|
2
2
|
export type { ImageModerationOptions } from "./image-moderation.js";
|
|
3
|
-
export { moderateVideo, __resetDefaultVideoClient, } from "./video-moderation.js";
|
|
4
|
-
export type { VideoModerationOptions } from "./video-moderation.js";
|
|
3
|
+
export { moderateVideo, DEFAULT_VIDEO_POLL_BACKOFF, __resetDefaultVideoClient, } from "./video-moderation.js";
|
|
4
|
+
export type { VideoModerationOptions, VideoPollBackoff, } from "./video-moderation.js";
|
|
5
5
|
export { moderateText, quickWordFilter, createWordListCache, } from "./text-moderation.js";
|
|
6
6
|
export type { WordListProvider, ModerateTextOptions, } from "./text-moderation.js";
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEpE,OAAO,EACL,aAAa,EACb,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEpE,OAAO,EACL,aAAa,EACb,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,YAAY,EACZ,eAAe,EACf,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC"}
|
package/dist/server/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { moderateImage, __resetDefaultVisionClient, } from "./image-moderation.js";
|
|
2
|
-
export { moderateVideo, __resetDefaultVideoClient, } from "./video-moderation.js";
|
|
2
|
+
export { moderateVideo, DEFAULT_VIDEO_POLL_BACKOFF, __resetDefaultVideoClient, } from "./video-moderation.js";
|
|
3
3
|
export { moderateText, quickWordFilter, createWordListCache, } from "./text-moderation.js";
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,aAAa,EACb,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,aAAa,EACb,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EACL,YAAY,EACZ,eAAe,EACf,mBAAmB,GACpB,MAAM,sBAAsB,CAAC","sourcesContent":["export {\n moderateImage,\n __resetDefaultVisionClient,\n} from \"./image-moderation.js\";\nexport type { ImageModerationOptions } from \"./image-moderation.js\";\n\nexport {\n moderateVideo,\n DEFAULT_VIDEO_POLL_BACKOFF,\n __resetDefaultVideoClient,\n} from \"./video-moderation.js\";\nexport type {\n VideoModerationOptions,\n VideoPollBackoff,\n} from \"./video-moderation.js\";\n\nexport {\n moderateText,\n quickWordFilter,\n createWordListCache,\n} from \"./text-moderation.js\";\nexport type {\n WordListProvider,\n ModerateTextOptions,\n} from \"./text-moderation.js\";\n"]}
|
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
import type { MediaModerationResult, ModerationLogger } from "../types.js";
|
|
2
2
|
import type { VideoIntelligenceServiceClient } from "@google-cloud/video-intelligence";
|
|
3
|
+
/** Poll cadence for the annotateVideo long-running operation. */
|
|
4
|
+
export interface VideoPollBackoff {
|
|
5
|
+
initialDelayMillis: number;
|
|
6
|
+
delayMultiplier: number;
|
|
7
|
+
maxDelayMillis: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Without an explicit `longrunning` backoff, gax polls the operation starting at
|
|
11
|
+
* 100ms (×1.3), which burns ~20 'Requests per minute' of Video Intelligence quota
|
|
12
|
+
* per video. Scans take tens of seconds, so the first poll waits 10s.
|
|
13
|
+
*/
|
|
14
|
+
export declare const DEFAULT_VIDEO_POLL_BACKOFF: VideoPollBackoff;
|
|
3
15
|
export interface VideoModerationOptions {
|
|
4
16
|
rejectionLikelihoods: ReadonlySet<string>;
|
|
5
17
|
logger?: ModerationLogger;
|
|
6
18
|
getClient?: () => Promise<VideoIntelligenceServiceClient>;
|
|
19
|
+
pollBackoff?: VideoPollBackoff;
|
|
7
20
|
}
|
|
8
21
|
/**
|
|
9
22
|
* Moderate a video via Google Cloud Video Intelligence.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video-moderation.d.ts","sourceRoot":"","sources":["../../src/server/video-moderation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAEvF,MAAM,WAAW,sBAAsB;IACrC,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,8BAA8B,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"video-moderation.d.ts","sourceRoot":"","sources":["../../src/server/video-moderation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAEvF,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,gBAIxC,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,8BAA8B,CAAC,CAAC;IAC1D,WAAW,CAAC,EAAE,gBAAgB,CAAC;CAChC;AAUD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CA0DhC;AAED,wBAAgB,yBAAyB,SAExC"}
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { isRejectionLikelihood, likelihoodToString, LIKELIHOOD_ORDER, } from "../likelihood.js";
|
|
2
|
+
/**
|
|
3
|
+
* Without an explicit `longrunning` backoff, gax polls the operation starting at
|
|
4
|
+
* 100ms (×1.3), which burns ~20 'Requests per minute' of Video Intelligence quota
|
|
5
|
+
* per video. Scans take tens of seconds, so the first poll waits 10s.
|
|
6
|
+
*/
|
|
7
|
+
export const DEFAULT_VIDEO_POLL_BACKOFF = {
|
|
8
|
+
initialDelayMillis: 10_000,
|
|
9
|
+
delayMultiplier: 1.5,
|
|
10
|
+
maxDelayMillis: 60_000,
|
|
11
|
+
};
|
|
2
12
|
let _defaultClient = null;
|
|
3
13
|
async function defaultGetVideoClient() {
|
|
4
14
|
if (_defaultClient)
|
|
@@ -17,11 +27,18 @@ export async function moderateVideo(gcsUri, options) {
|
|
|
17
27
|
logger?.info?.(`[moderation-core] Video moderation: ${gcsUri}`);
|
|
18
28
|
const { protos } = await import("@google-cloud/video-intelligence");
|
|
19
29
|
const client = await getClient();
|
|
30
|
+
const pollBackoff = options.pollBackoff ?? DEFAULT_VIDEO_POLL_BACKOFF;
|
|
20
31
|
const [operation] = await client.annotateVideo({
|
|
21
32
|
inputUri: gcsUri,
|
|
22
33
|
features: [
|
|
23
34
|
protos.google.cloud.videointelligence.v1.Feature.EXPLICIT_CONTENT_DETECTION,
|
|
24
35
|
],
|
|
36
|
+
}, {
|
|
37
|
+
longrunning: {
|
|
38
|
+
initialRetryDelayMillis: pollBackoff.initialDelayMillis,
|
|
39
|
+
retryDelayMultiplier: pollBackoff.delayMultiplier,
|
|
40
|
+
maxRetryDelayMillis: pollBackoff.maxDelayMillis,
|
|
41
|
+
},
|
|
25
42
|
});
|
|
26
43
|
const [result] = await operation.promise();
|
|
27
44
|
const annotation = result.annotationResults?.[0];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video-moderation.js","sourceRoot":"","sources":["../../src/server/video-moderation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"video-moderation.js","sourceRoot":"","sources":["../../src/server/video-moderation.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n isRejectionLikelihood,\n likelihoodToString,\n LIKELIHOOD_ORDER,\n} from \"../likelihood.js\";\nimport type {\n Likelihood,\n MediaModerationResult,\n ModerationLogger,\n} from \"../types.js\";\n\nimport type { VideoIntelligenceServiceClient } from \"@google-cloud/video-intelligence\";\n\n/** Poll cadence for the annotateVideo long-running operation. */\nexport interface VideoPollBackoff {\n initialDelayMillis: number;\n delayMultiplier: number;\n maxDelayMillis: number;\n}\n\n/**\n * Without an explicit `longrunning` backoff, gax polls the operation starting at\n * 100ms (×1.3), which burns ~20 'Requests per minute' of Video Intelligence quota\n * per video. Scans take tens of seconds, so the first poll waits 10s.\n */\nexport const DEFAULT_VIDEO_POLL_BACKOFF: VideoPollBackoff = {\n initialDelayMillis: 10_000,\n delayMultiplier: 1.5,\n maxDelayMillis: 60_000,\n};\n\nexport interface VideoModerationOptions {\n rejectionLikelihoods: ReadonlySet<string>;\n logger?: ModerationLogger;\n getClient?: () => Promise<VideoIntelligenceServiceClient>;\n pollBackoff?: VideoPollBackoff;\n}\n\nlet _defaultClient: VideoIntelligenceServiceClient | null = null;\nasync function defaultGetVideoClient(): Promise<VideoIntelligenceServiceClient> {\n if (_defaultClient) return _defaultClient;\n const mod = await import(\"@google-cloud/video-intelligence\");\n _defaultClient = new mod.VideoIntelligenceServiceClient();\n return _defaultClient;\n}\n\n/**\n * Moderate a video via Google Cloud Video Intelligence.\n * @param gcsUri - MUST be a GCS URI (\"gs://bucket/path\"); HTTPS URLs are not supported by the API.\n */\nexport async function moderateVideo(\n gcsUri: string,\n options: VideoModerationOptions,\n): Promise<MediaModerationResult> {\n const { rejectionLikelihoods, logger } = options;\n const getClient = options.getClient ?? defaultGetVideoClient;\n\n logger?.info?.(`[moderation-core] Video moderation: ${gcsUri}`);\n\n const { protos } = await import(\"@google-cloud/video-intelligence\");\n const client = await getClient();\n\n const pollBackoff = options.pollBackoff ?? DEFAULT_VIDEO_POLL_BACKOFF;\n const [operation] = await client.annotateVideo(\n {\n inputUri: gcsUri,\n features: [\n protos.google.cloud.videointelligence.v1.Feature.EXPLICIT_CONTENT_DETECTION,\n ],\n },\n {\n longrunning: {\n initialRetryDelayMillis: pollBackoff.initialDelayMillis,\n retryDelayMultiplier: pollBackoff.delayMultiplier,\n maxRetryDelayMillis: pollBackoff.maxDelayMillis,\n },\n },\n );\n\n const [result] = await operation.promise();\n const annotation = result.annotationResults?.[0];\n const explicitAnnotation = annotation?.explicitAnnotation;\n\n if (!explicitAnnotation?.frames?.length) {\n logger?.warn?.(\"[moderation-core] No explicit-content frames returned; allowing content\");\n return { safe: true, scores: { adult: \"UNKNOWN\", violence: \"UNKNOWN\", racy: \"UNKNOWN\" } };\n }\n\n let maxAdult: Likelihood = \"VERY_UNLIKELY\";\n let foundExplicit = false;\n\n for (const frame of explicitAnnotation.frames) {\n if (isRejectionLikelihood(frame.pornographyLikelihood, rejectionLikelihoods)) {\n maxAdult = likelihoodToString(frame.pornographyLikelihood);\n foundExplicit = true;\n break;\n }\n const current = likelihoodToString(frame.pornographyLikelihood);\n if (LIKELIHOOD_ORDER[current] > LIKELIHOOD_ORDER[maxAdult]) {\n maxAdult = current;\n }\n }\n\n const safe = !foundExplicit;\n const reason = safe ? undefined : \"Adult or sexually explicit content is not allowed\";\n\n return {\n safe,\n reason,\n scores: { adult: maxAdult, violence: \"NOT_CHECKED\", racy: \"NOT_CHECKED\" },\n };\n}\n\nexport function __resetDefaultVideoClient() {\n _defaultClient = null;\n}\n"]}
|