-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13 from edenartlab/stage
refactor, stories, reliability
- Loading branch information
Showing
28 changed files
with
572 additions
and
646 deletions.
There are no files selected for viewing
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
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,3 @@ | ||
from .monologue import animated_monologue | ||
from .dialogue import animated_dialogue | ||
from .story import animated_story |
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,48 @@ | ||
from typing import Optional | ||
|
||
from ..plugins import replicate, elevenlabs, s3 | ||
from ..character import EdenCharacter | ||
from ..utils import combine_speech_video | ||
|
||
|
||
def talking_head( | ||
character: EdenCharacter, | ||
text: str, | ||
width: Optional[int] = None, | ||
height: Optional[int] = None | ||
) -> str: | ||
audio_bytes = elevenlabs.tts( | ||
text, | ||
voice=character.voice | ||
) | ||
audio_url = s3.upload(audio_bytes, "mp3") | ||
output_url, thumbnail_url = replicate.wav2lip( | ||
face_url=character.image, | ||
speech_url=audio_url, | ||
gfpgan=False, | ||
gfpgan_upscale=1, | ||
width=width, | ||
height=height, | ||
) | ||
return output_url, thumbnail_url | ||
|
||
|
||
def screenplay_clip( | ||
character: EdenCharacter, | ||
speech: str, | ||
image_text: str, | ||
width: Optional[int] = None, | ||
height: Optional[int] = None | ||
) -> str: | ||
audio_bytes = elevenlabs.tts( | ||
speech, | ||
voice=character.voice | ||
) | ||
audio_url = s3.upload(audio_bytes, "mp3") | ||
video_url, thumbnail_url = replicate.txt2vid( | ||
interpolation_texts=[image_text], | ||
width=width, | ||
height=height, | ||
) | ||
output_filename = combine_speech_video(audio_url, video_url) | ||
return output_filename, thumbnail_url |
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,67 @@ | ||
import os | ||
import requests | ||
import tempfile | ||
from concurrent.futures import ThreadPoolExecutor, as_completed | ||
|
||
from .. import utils | ||
from .animation import talking_head | ||
from ..plugins import replicate, elevenlabs, s3 | ||
from ..character import EdenCharacter | ||
from ..scenarios import dialogue | ||
from ..models import DialogueRequest | ||
|
||
MAX_PIXELS = 1024 * 1024 | ||
MAX_WORKERS = 3 | ||
|
||
|
||
def animated_dialogue(request: DialogueRequest): | ||
result = dialogue(request) | ||
print(result) | ||
|
||
characters = { | ||
character_id: EdenCharacter(character_id) | ||
for character_id in request.character_ids | ||
} | ||
images = [ | ||
characters[character_id].image | ||
for character_id in request.character_ids | ||
] | ||
width, height = utils.calculate_target_dimensions(images, MAX_PIXELS) | ||
|
||
def run_talking_head_segment(message): | ||
character = characters[message["character_id"]] | ||
output, _ = talking_head( | ||
character, | ||
message["message"], | ||
width, | ||
height | ||
) | ||
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as temp_file: | ||
response = requests.get(output, stream=True) | ||
response.raise_for_status() | ||
for chunk in response.iter_content(chunk_size=8192): | ||
temp_file.write(chunk) | ||
temp_file.flush() | ||
return temp_file.name | ||
|
||
video_files = utils.process_in_parallel( | ||
result.dialogue, | ||
run_talking_head_segment, | ||
max_workers=MAX_WORKERS | ||
) | ||
|
||
# concatenate the final video clips | ||
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as temp_output_file: | ||
utils.concatenate_videos(video_files, temp_output_file.name) | ||
with open(temp_output_file.name, 'rb') as f: | ||
video_bytes = f.read() | ||
output_url = s3.upload(video_bytes, "mp4") | ||
os.remove(temp_output_file.name) | ||
for video_file in video_files: | ||
os.remove(video_file) | ||
|
||
# generate thumbnail | ||
thumbnail = utils.create_dialogue_thumbnail(*images, width, height) | ||
thumbnail_url = s3.upload(thumbnail, "webp") | ||
|
||
return output_url, thumbnail_url |
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,17 @@ | ||
import requests | ||
|
||
from .animation import talking_head | ||
from ..plugins import replicate, elevenlabs, s3 | ||
from ..character import EdenCharacter | ||
from ..scenarios import monologue | ||
from ..models import MonologueRequest | ||
|
||
|
||
def animated_monologue(request: MonologueRequest): | ||
character = EdenCharacter(request.character_id) | ||
result = monologue(request) | ||
print(result) | ||
output, thumbnail_url = talking_head(character, result.monologue) | ||
output_bytes = requests.get(output).content | ||
output_url = s3.upload(output_bytes, "mp4") | ||
return output_url, thumbnail_url |
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,71 @@ | ||
import os | ||
import requests | ||
import tempfile | ||
|
||
from .. import utils | ||
from ..plugins import replicate, elevenlabs, s3 | ||
from ..character import EdenCharacter | ||
from ..scenarios import story | ||
from ..models import StoryRequest, StoryResult | ||
from .animation import screenplay_clip | ||
|
||
MAX_PIXELS = 1024 * 1024 | ||
MAX_WORKERS = 3 | ||
|
||
|
||
def animated_story(request: StoryRequest): | ||
screenplay = story(request) | ||
print(screenplay) | ||
|
||
characters = { | ||
character_id: EdenCharacter(character_id) | ||
for character_id in request.character_ids + [request.narrator_id] | ||
} | ||
|
||
character_name_lookup = { | ||
character.name: character_id | ||
for character_id, character in characters.items() | ||
} | ||
|
||
images = [ | ||
characters[character_id].image | ||
for character_id in request.character_ids | ||
] | ||
|
||
width, height = utils.calculate_target_dimensions(images, MAX_PIXELS) | ||
|
||
def run_story_segment(clip): | ||
if clip['voiceover'] == 'character': | ||
character_id = character_name_lookup[clip['character']] | ||
character = characters[character_id] | ||
else: | ||
character = characters[request.narrator_id] | ||
output_filename, thumbnail_url = screenplay_clip( | ||
character, | ||
clip['speech'], | ||
clip['image_description'], | ||
width, | ||
height | ||
) | ||
return output_filename, thumbnail_url | ||
|
||
results = utils.process_in_parallel( | ||
screenplay['clips'], | ||
run_story_segment, | ||
max_workers=MAX_WORKERS | ||
) | ||
|
||
video_files = [video_file for video_file, thumbnail in results] | ||
thumbnail_url = results[0][1] | ||
|
||
with tempfile.NamedTemporaryFile(delete=True, suffix=".mp4") as temp_output_file: | ||
utils.concatenate_videos(video_files, temp_output_file.name) | ||
with open(temp_output_file.name, 'rb') as f: | ||
video_bytes = f.read() | ||
output_url = s3.upload(video_bytes, "mp4") | ||
|
||
# clean up clips | ||
for video_file in video_files: | ||
os.remove(video_file) | ||
|
||
return output_url, thumbnail_url |
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
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
Oops, something went wrong.