-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* spiritme init * new components * pnpm-lock.yaml * fix pagination
- Loading branch information
1 parent
0355b13
commit 1f789b1
Showing
6 changed files
with
429 additions
and
7 deletions.
There are no files selected for viewing
160 changes: 160 additions & 0 deletions
160
components/spiritme/actions/generate-video/generate-video.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
import spiritme from "../../spiritme.app.mjs"; | ||
import { ConfigurationError } from "@pipedream/platform"; | ||
|
||
export default { | ||
key: "spiritme-generate-video", | ||
name: "Generate Video", | ||
description: "Generates a new video using specific voice and avatar props. [See the documentation](https://api.spiritme.tech/api/swagger/#/videos/videos_create)", | ||
version: "0.0.1", | ||
type: "action", | ||
props: { | ||
spiritme, | ||
name: { | ||
type: "string", | ||
label: "Name", | ||
description: "Name of the video", | ||
}, | ||
avatar: { | ||
propDefinition: [ | ||
spiritme, | ||
"avatar", | ||
], | ||
}, | ||
voice: { | ||
propDefinition: [ | ||
spiritme, | ||
"voice", | ||
], | ||
}, | ||
text: { | ||
type: "string", | ||
label: "Text", | ||
description: "The text to use for the video. Example: `Hello everyone! I am a virtual avatar from Spiritme.` Use tags `<emotion name=\"emotion_name\"> text </emotion>` to add emotions to the generated video. The list of supported emotions are `neutral`, `semismile`, `smile`, `happiness`, `sadness`, and `surprise`. Either text or audio file is required.", | ||
optional: true, | ||
}, | ||
audioFile: { | ||
propDefinition: [ | ||
spiritme, | ||
"file", | ||
() => ({ | ||
type: [ | ||
"audio", | ||
], | ||
}), | ||
], | ||
label: "Audio File", | ||
description: "Identifier of an audio file. Either text or audio file is required.", | ||
}, | ||
media: { | ||
propDefinition: [ | ||
spiritme, | ||
"file", | ||
() => ({ | ||
type: [ | ||
"image", | ||
"video", | ||
], | ||
}), | ||
], | ||
label: "Media File", | ||
description: "Identifier of an image or video file. One of avatar or media is required.", | ||
}, | ||
viewType: { | ||
type: "string", | ||
label: "View Type", | ||
description: "Content as is or content in circle. Supported only for avatars.", | ||
optional: true, | ||
options: [ | ||
"rectangular", | ||
"circular", | ||
], | ||
}, | ||
autoEmotionsMarkup: { | ||
type: "boolean", | ||
label: "Auto Emotions Markup", | ||
description: "Add emotions automatically by AI", | ||
optional: true, | ||
}, | ||
waitForCompletion: { | ||
type: "boolean", | ||
label: "Wait For Completion", | ||
description: "Set to `true` to poll the API in 3-second intervals until the video is completed", | ||
optional: true, | ||
}, | ||
}, | ||
async run({ $ }) { | ||
const { | ||
spiritme, | ||
name, | ||
avatar, | ||
voice, | ||
text, | ||
audioFile, | ||
media, | ||
viewType, | ||
autoEmotionsMarkup, | ||
waitForCompletion, | ||
} = this; | ||
|
||
if (!avatar && !media) { | ||
throw new ConfigurationError("One of `Avatar` or `Media File` is required"); | ||
} | ||
|
||
if (!text && !audioFile) { | ||
throw new ConfigurationError("One of `Text` or `Audio File` is required"); | ||
} | ||
|
||
let response = await spiritme.generateVideo({ | ||
$, | ||
data: { | ||
name, | ||
slides: [ | ||
{ | ||
audio_source: { | ||
text, | ||
voice: voice | ||
? { | ||
id: voice, | ||
} | ||
: undefined, | ||
file: audioFile | ||
? { | ||
id: audioFile, | ||
} | ||
: undefined, | ||
}, | ||
layers: [ | ||
{ | ||
avatar: avatar | ||
? { | ||
id: avatar, | ||
} | ||
: undefined, | ||
media: media | ||
? { | ||
id: media, | ||
} | ||
: undefined, | ||
view_type: viewType, | ||
}, | ||
], | ||
}, | ||
], | ||
auto_emotions_markup: autoEmotionsMarkup, | ||
}, | ||
}); | ||
|
||
if (waitForCompletion) { | ||
const timer = (ms) => new Promise((res) => setTimeout(res, ms)); | ||
while (response.status !== "success") { | ||
response = await spiritme.getVideo({ | ||
videoId: response.id, | ||
}); | ||
await timer(3000); | ||
} | ||
} | ||
|
||
$.export("$summary", `Generated video with ID: ${response.id}`); | ||
return response; | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
components/spiritme/sources/new-avatar-video-completion/new-avatar-video-completion.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import spiritme from "../../spiritme.app.mjs"; | ||
import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; | ||
import sampleEmit from "./test-event.mjs"; | ||
|
||
export default { | ||
key: "spiritme-new-avatar-video-completion", | ||
name: "New Avatar Video Completion", | ||
description: "Emit new event when an avatar video completes rendering.", | ||
version: "0.0.1", | ||
type: "source", | ||
dedupe: "unique", | ||
props: { | ||
spiritme, | ||
db: "$.service.db", | ||
timer: { | ||
type: "$.interface.timer", | ||
default: { | ||
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, | ||
}, | ||
}, | ||
}, | ||
hooks: { | ||
async deploy() { | ||
await this.processEvent(25); | ||
}, | ||
}, | ||
methods: { | ||
_getLastTs() { | ||
return this.db.get("lastTs") || 0; | ||
}, | ||
_setLastTs(lastTs) { | ||
this.db.set("lastTs", lastTs); | ||
}, | ||
emitEvent(video) { | ||
const meta = this.generateMeta(video); | ||
this.$emit(video, meta); | ||
}, | ||
generateMeta(video) { | ||
return { | ||
id: video.id, | ||
summary: `New Video: ${video.name}`, | ||
ts: Date.parse(video.gd), | ||
}; | ||
}, | ||
async processEvent(max) { | ||
const lastTs = this._getLastTs(); | ||
const params = { | ||
limit: 100, | ||
offset: 0, | ||
status: [ | ||
"success", | ||
], | ||
}; | ||
let total; | ||
|
||
const videos = []; | ||
do { | ||
const { results } = await this.spiritme.listVideos({ | ||
params, | ||
}); | ||
for (const video of results) { | ||
const ts = Date.parse(video.gd); | ||
if (ts >= lastTs && (!max || videos.length < max)) { | ||
videos.push(video); | ||
} else { | ||
break; | ||
} | ||
} | ||
params.offset += params.limit; | ||
total = results?.length; | ||
} while (total === params.limit && (!max || videos.length < max)); | ||
|
||
if (!videos.length) { | ||
return; | ||
} | ||
|
||
this._setLastTs(Date.parse(videos[0].gd)); | ||
videos.reverse().forEach((video) => this.emitEvent(video)); | ||
}, | ||
}, | ||
async run() { | ||
await this.processEvent(); | ||
}, | ||
sampleEmit, | ||
}; |
51 changes: 51 additions & 0 deletions
51
components/spiritme/sources/new-avatar-video-completion/test-event.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
export default { | ||
"id": 85987, | ||
"cd": "2024-06-28T21:32:14.878982Z", | ||
"gd": "2024-06-28T21:34:37.340485Z", | ||
"name": "Video", | ||
"slides": [ | ||
{ | ||
"id": 1, | ||
"audio_source": { | ||
"text": "<emotion name=\"happiness\">Pipedream is the best!</emotion>", | ||
"voice": { | ||
"id": 18, | ||
"name": "Kimberly", | ||
"label": "English Kimberly", | ||
"provider": "amazon", | ||
"sex": "female" | ||
}, | ||
"file": null | ||
}, | ||
"layers": [ | ||
{ | ||
"id": 1, | ||
"avatar": { | ||
"id": 9889, | ||
"name": "Elizabeth", | ||
"preview": "https://cdn.spiritme.tech/media/avatars/previews/ec724f6e58a22d3ec9dd81fe825f3eb1ea2a99b6.png", | ||
"frame_width": 1073, | ||
"frame_height": 1177 | ||
}, | ||
"media": null, | ||
"x": 0.5, | ||
"y": 1, | ||
"scale": 1, | ||
"crop": null, | ||
"view_type": "rectangular" | ||
} | ||
], | ||
"background": null | ||
} | ||
], | ||
"webhook": null, | ||
"resolution": { | ||
"width": 1920, | ||
"height": 1080 | ||
}, | ||
"auto_emotions_markup": true, | ||
"enable_subtitles": false, | ||
"status": "success", | ||
"result": "https://cdn.spiritme.tech/media/videos/3fa94ae367237676442cde44feacaf5c24875966.mp4", | ||
"thumbnail": "https://cdn.spiritme.tech/media/videos/65dd50bc2b996b3457fcb4d98ce5c270bed54a6d.jpeg" | ||
} |
Oops, something went wrong.