Compare commits
4 commits
90f1954317
...
e3ae1367d6
| Author | SHA1 | Date | |
|---|---|---|---|
| e3ae1367d6 | |||
| ccbde02107 | |||
| 73e22ed685 | |||
| 4b3b225a2c |
8 changed files with 185 additions and 70 deletions
|
|
@ -265,6 +265,15 @@ examples (config.SITENAME.jsonc) that are part of this pan.do/ra distribution.
|
||||||
"find": true,
|
"find": true,
|
||||||
"sort": true
|
"sort": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "character",
|
||||||
|
"title": "Character",
|
||||||
|
"type": "string",
|
||||||
|
"columnWidth": 128,
|
||||||
|
"filter": true,
|
||||||
|
"find": true,
|
||||||
|
"sort": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "prompt",
|
"id": "prompt",
|
||||||
"title": "Prompt",
|
"title": "Prompt",
|
||||||
|
|
|
||||||
7
db/reload.sh
Executable file
7
db/reload.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh
|
||||||
|
pandoractl stop
|
||||||
|
sudo -H -u postgres dropdb pandora
|
||||||
|
sudo -H -u postgres createdb -T template0 --locale=C --encoding=UTF8 -O pandora pandora
|
||||||
|
zcat /srv/pandora/data/db/latest.psql.gz | pandoractl manage dbshell
|
||||||
|
pandoractl start
|
||||||
|
|
||||||
5
db/sync_pandora.sh
Executable file
5
db/sync_pandora.sh
Executable file
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
rsync -avP time:/srv/pandora/data/ /srv/pandora/data/
|
||||||
|
bash /srv/pandora/data/db/reload.sh
|
||||||
|
rsync -avP time:/srv/pandora/data/ /srv/pandora/data/ --delete
|
||||||
|
pandoractl manage generate_clips
|
||||||
4
db/update.sh
Executable file
4
db/update.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/bash
|
||||||
|
cd /srv/pandora/data/db
|
||||||
|
pg_dump pandora | gzip > pandora-`date -I`.psql.gz
|
||||||
|
ln -sf pandora-`date -I`.psql.gz latest.psql.gz
|
||||||
8
etc/systemd/system/pandora-backup-db.service
Normal file
8
etc/systemd/system/pandora-backup-db.service
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
Unit]
|
||||||
|
Description=Backup pandora database
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
User=pandora
|
||||||
|
Group=pandora
|
||||||
|
ExecStart=/srv/pandora/db/update.sh
|
||||||
9
etc/systemd/system/pandora-backup-db.timer
Normal file
9
etc/systemd/system/pandora-backup-db.timer
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Backup pandora database
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=*-*-* 4:00
|
||||||
|
Persistent=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
198
generate.py
198
generate.py
|
|
@ -16,6 +16,7 @@ from django.conf import settings
|
||||||
from item.models import Item
|
from item.models import Item
|
||||||
from document.models import Document
|
from document.models import Document
|
||||||
from archive.models import File, Stream
|
from archive.models import File, Stream
|
||||||
|
import itemlist.models
|
||||||
|
|
||||||
|
|
||||||
os.environ["FAL_KEY"] = settings.FAL_KEY
|
os.environ["FAL_KEY"] = settings.FAL_KEY
|
||||||
|
|
@ -34,7 +35,7 @@ def public_url(path):
|
||||||
def public_document_url(document):
|
def public_document_url(document):
|
||||||
url = "%sdocuments/%s/source.%s?token=%s" % (
|
url = "%sdocuments/%s/source.%s?token=%s" % (
|
||||||
settings.PUBLIC_URL,
|
settings.PUBLIC_URL,
|
||||||
ox.toAZ(document.id),
|
document.get_id(),
|
||||||
document.extension,
|
document.extension,
|
||||||
settings.PUBLIC_TOKEN,
|
settings.PUBLIC_TOKEN,
|
||||||
)
|
)
|
||||||
|
|
@ -89,6 +90,64 @@ def trim_video(src, dst, frames, start0=False):
|
||||||
out.release()
|
out.release()
|
||||||
cap.release()
|
cap.release()
|
||||||
|
|
||||||
|
def make_single_character_image(character):
|
||||||
|
character = get_character_document(character, type='Character')
|
||||||
|
character_url = public_document_url(character)
|
||||||
|
data = {
|
||||||
|
"model": "seedream-4-5-251128",
|
||||||
|
"size": "2K",
|
||||||
|
"watermark": False,
|
||||||
|
'image': character_url,
|
||||||
|
"prompt": "character from image 1 is standing straight up, full body portrait from head to toe. face, clothing, skin are photo realistic, camera facing straight at character. background is white"
|
||||||
|
}
|
||||||
|
url = bytedance_image_generation(data)
|
||||||
|
extension = url.split(".")[-1].split("?")[0]
|
||||||
|
if extension == "jpeg":
|
||||||
|
extension = "jpg"
|
||||||
|
file = Document(user=character.user)
|
||||||
|
file.data["title"] = character.data['title'].replace('Character', 'Single Character')
|
||||||
|
file.extension = extension
|
||||||
|
file.width = -1
|
||||||
|
file.pages = -1
|
||||||
|
file.uploading = True
|
||||||
|
file.save()
|
||||||
|
file.uploading = True
|
||||||
|
name = "data.%s" % file.extension
|
||||||
|
file.file.name = file.path(name)
|
||||||
|
ox.net.save_url(url, file.file.path, overwrite=True)
|
||||||
|
file.get_info()
|
||||||
|
file.get_ratio()
|
||||||
|
file.oshash = ox.oshash(file.file.path)
|
||||||
|
file.save()
|
||||||
|
file.update_sort()
|
||||||
|
return file
|
||||||
|
|
||||||
|
def make_single_character_image_flux(character):
|
||||||
|
character = get_character_document(character, type='Character')
|
||||||
|
character_url = public_document_url(character)
|
||||||
|
prompt = 'character from @image 1 is standing straight up, full body portrait from head to toe. face, clothing, skin are photo realistic, camera facing straight at character. background is white'
|
||||||
|
url = flux_edit_image([character_url], prompt)
|
||||||
|
extension = url.split(".")[-1].split("?")[0]
|
||||||
|
if extension == "jpeg":
|
||||||
|
extension = "jpg"
|
||||||
|
file = Document(user=character.user)
|
||||||
|
file.data["title"] = character.data['title'].replace('Character', 'FLUX Single Character')
|
||||||
|
file.extension = extension
|
||||||
|
file.width = -1
|
||||||
|
file.pages = -1
|
||||||
|
file.uploading = True
|
||||||
|
file.save()
|
||||||
|
file.uploading = True
|
||||||
|
name = "data.%s" % file.extension
|
||||||
|
file.file.name = file.path(name)
|
||||||
|
ox.net.save_url(url, file.file.path, overwrite=True)
|
||||||
|
file.get_info()
|
||||||
|
file.get_ratio()
|
||||||
|
file.oshash = ox.oshash(file.file.path)
|
||||||
|
file.save()
|
||||||
|
file.update_sort()
|
||||||
|
return file
|
||||||
|
|
||||||
|
|
||||||
def bytedance_task(data):
|
def bytedance_task(data):
|
||||||
url = "https://ark.ap-southeast.bytepluses.com/api/v3/contents/generations/tasks"
|
url = "https://ark.ap-southeast.bytepluses.com/api/v3/contents/generations/tasks"
|
||||||
|
|
@ -394,6 +453,10 @@ def process_frame(item, prompt, character=None, position=0, seed=None):
|
||||||
img.update_find()
|
img.update_find()
|
||||||
return img
|
return img
|
||||||
|
|
||||||
|
def get_character_document(character, type="Single Character"):
|
||||||
|
if character in ("P1", "P2", "P3", "P4", "P5"):
|
||||||
|
return Document.objects.get(data__title=type + " " + character)
|
||||||
|
return character
|
||||||
|
|
||||||
"""
|
"""
|
||||||
REPLACE_CHARACTER_PROMPT = "Replace the foreground character in image 1 with the character in image 2, keep the posture, clothing, background, light, atmosphere from image 1, but take the facial features and personality from image 2. Make sure the size of the character is adjusted since the new character is a child and make sure the size of the head matches the body. The quality of the image should be the same between foreground and background, adjust the quality of the character to match the background. Use the style of image 1 for the character: if image 1 is a photo make the character a real person, if image 1 is a drawing make the character a drawn character, if image 1 is a comic use a comic character and so on"
|
REPLACE_CHARACTER_PROMPT = "Replace the foreground character in image 1 with the character in image 2, keep the posture, clothing, background, light, atmosphere from image 1, but take the facial features and personality from image 2. Make sure the size of the character is adjusted since the new character is a child and make sure the size of the head matches the body. The quality of the image should be the same between foreground and background, adjust the quality of the character to match the background. Use the style of image 1 for the character: if image 1 is a photo make the character a real person, if image 1 is a drawing make the character a drawn character, if image 1 is a comic use a comic character and so on"
|
||||||
|
|
@ -410,8 +473,8 @@ def fal_replace_character(item, character, position=0):
|
||||||
)
|
)
|
||||||
if character == "P5":
|
if character == "P5":
|
||||||
prompt = prompt.replace("child", "teenager")
|
prompt = prompt.replace("child", "teenager")
|
||||||
if character in ("P1", "P2", "P3", "P4", "P5"):
|
|
||||||
character = Document.objects.get(data__title="Character " + character)
|
character = get_character_document(character)
|
||||||
if isinstance(character, Document):
|
if isinstance(character, Document):
|
||||||
character = public_document_url(character)
|
character = public_document_url(character)
|
||||||
image = public_frame_url(item, position)
|
image = public_frame_url(item, position)
|
||||||
|
|
@ -423,6 +486,11 @@ def fal_replace_character(item, character, position=0):
|
||||||
img.data["prompt"] = prompt
|
img.data["prompt"] = prompt
|
||||||
img.data["source"] = item.public_id
|
img.data["source"] = item.public_id
|
||||||
img.data["source"] += " " + character.split("?")[0]
|
img.data["source"] += " " + character.split("?")[0]
|
||||||
|
if isinstance(character, Document):
|
||||||
|
img.data["character"] = character.get_id()
|
||||||
|
else:
|
||||||
|
img.data["character"] = character
|
||||||
|
img.data["position"] = position
|
||||||
print(img, img.data)
|
print(img, img.data)
|
||||||
img.save()
|
img.save()
|
||||||
img.update_sort()
|
img.update_sort()
|
||||||
|
|
@ -434,11 +502,19 @@ def replace_character(item, character, position=0, seed=None):
|
||||||
prompt = REPLACE_CHARACTER_PROMPT
|
prompt = REPLACE_CHARACTER_PROMPT
|
||||||
if character == "P5":
|
if character == "P5":
|
||||||
prompt = prompt.replace("child", "teenager")
|
prompt = prompt.replace("child", "teenager")
|
||||||
if character in ("P1", "P2", "P3", "P4", "P5"):
|
character = get_character_document(character)
|
||||||
character = public_document_url(
|
if isinstance(character, Document):
|
||||||
Document.objects.get(data__title="Character " + character)
|
character_url = public_document_url(character)
|
||||||
)
|
else:
|
||||||
return process_frame(item, prompt, character, position, seed=seed)
|
character_url = character
|
||||||
|
frame = process_frame(item, prompt, character_url, position, seed=seed)
|
||||||
|
if isinstance(character, Document):
|
||||||
|
frame.data["character"] = character.get_id()
|
||||||
|
else:
|
||||||
|
frame.data["character"] = character
|
||||||
|
frame.data["position"] = position
|
||||||
|
frame.save()
|
||||||
|
return frame
|
||||||
|
|
||||||
|
|
||||||
def kling_lipsync(audio_item, video_item):
|
def kling_lipsync(audio_item, video_item):
|
||||||
|
|
@ -474,10 +550,15 @@ def kling_v2v_reference(item, character, keep=False):
|
||||||
character = public_document_url(
|
character = public_document_url(
|
||||||
Document.objects.get(data__title="Character " + character)
|
Document.objects.get(data__title="Character " + character)
|
||||||
)
|
)
|
||||||
|
character = get_character_document(character)
|
||||||
|
if isinstance(character, Document):
|
||||||
|
character_url = public_document_url(character)
|
||||||
|
else:
|
||||||
|
character_url = character
|
||||||
video_url = public_video_url(item)
|
video_url = public_video_url(item)
|
||||||
prompt = "Replace the main character in @Video1 with the character from the reference images, adjust the style of the character to match the style of the video"
|
prompt = "Replace the main character in @Video1 with the character from the reference images, adjust the style of the character to match the style of the video"
|
||||||
model = "fal-ai/kling-video/o1/video-to-video/reference"
|
model = "fal-ai/kling-video/o1/video-to-video/reference"
|
||||||
prompt_hash = hashlib.sha1((prompt + character).encode()).hexdigest()
|
prompt_hash = hashlib.sha1((prompt + character_url).encode()).hexdigest()
|
||||||
output = "/srv/pandora/static/power/cache/%s_%s/ai.mp4" % (
|
output = "/srv/pandora/static/power/cache/%s_%s/ai.mp4" % (
|
||||||
item.public_id,
|
item.public_id,
|
||||||
prompt_hash,
|
prompt_hash,
|
||||||
|
|
@ -499,7 +580,7 @@ def kling_v2v_reference(item, character, keep=False):
|
||||||
"keep_audio": False,
|
"keep_audio": False,
|
||||||
"aspect_ratio": "16:9",
|
"aspect_ratio": "16:9",
|
||||||
"video_url": video_url,
|
"video_url": video_url,
|
||||||
"image_urls": [image_url],
|
"image_urls": [character_url],
|
||||||
"duration": str(duration)
|
"duration": str(duration)
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
@ -624,11 +705,14 @@ def reshoot_item(item, extra_prompt=None, first_frame=None, keep=False, prompt=N
|
||||||
if isinstance(item, str):
|
if isinstance(item, str):
|
||||||
item = Item.objects.get(public_id=item)
|
item = Item.objects.get(public_id=item)
|
||||||
if isinstance(first_frame, Document):
|
if isinstance(first_frame, Document):
|
||||||
first_frame = public_document_url(first_frame)
|
first_frame_url = public_document_url(first_frame)
|
||||||
|
else:
|
||||||
|
first_frame_url = first_frame
|
||||||
duration = item.sort.duration
|
duration = item.sort.duration
|
||||||
frames = int(duration * 24)
|
frames = int(duration * 24)
|
||||||
|
neutral = first_frame is not None
|
||||||
if prompt is None:
|
if prompt is None:
|
||||||
prompt = describe_item(item, first_frame is not None)
|
prompt = describe_item(item, neutral)
|
||||||
if extra_prompt:
|
if extra_prompt:
|
||||||
prompt += " " + extra_prompt
|
prompt += " " + extra_prompt
|
||||||
prompt_hash = hashlib.sha1((prompt).encode()).hexdigest()
|
prompt_hash = hashlib.sha1((prompt).encode()).hexdigest()
|
||||||
|
|
@ -637,7 +721,7 @@ def reshoot_item(item, extra_prompt=None, first_frame=None, keep=False, prompt=N
|
||||||
prompt_hash,
|
prompt_hash,
|
||||||
)
|
)
|
||||||
if first_frame:
|
if first_frame:
|
||||||
status = i2v_bytedance(first_frame, prompt, duration, output)
|
status = i2v_bytedance(first_frame_url, prompt, duration, output)
|
||||||
else:
|
else:
|
||||||
status = t2v_bytedance(prompt, duration, output)
|
status = t2v_bytedance(prompt, duration, output)
|
||||||
|
|
||||||
|
|
@ -654,9 +738,11 @@ def reshoot_item(item, extra_prompt=None, first_frame=None, keep=False, prompt=N
|
||||||
ai.data["model"] = status["model"]
|
ai.data["model"] = status["model"]
|
||||||
ai.data["seed"] = status["seed"]
|
ai.data["seed"] = status["seed"]
|
||||||
if first_frame:
|
if first_frame:
|
||||||
ai.data["firstframe"] = first_frame.split("?")[0]
|
|
||||||
if isinstance(first_frame, Document):
|
if isinstance(first_frame, Document):
|
||||||
first_frame.add(ai)
|
first_frame.add(ai)
|
||||||
|
ai.data["firstframe"] = first_frame.get_id()
|
||||||
|
else:
|
||||||
|
ai.data["firstframe"] = first_frame.split("?")[0]
|
||||||
ai.save()
|
ai.save()
|
||||||
if not keep:
|
if not keep:
|
||||||
shutil.rmtree(os.path.dirname(output))
|
shutil.rmtree(os.path.dirname(output))
|
||||||
|
|
@ -719,7 +805,7 @@ def reshoot_item_segments(item, character, keep=False):
|
||||||
ai = add_ai_variant(item, joined_output, "ai:0:reshoot-firstframe")
|
ai = add_ai_variant(item, joined_output, "ai:0:reshoot-firstframe")
|
||||||
prompt = "\n\n".join(prompts)
|
prompt = "\n\n".join(prompts)
|
||||||
ai.data["prompt"] = ox.escape_html(prompt)
|
ai.data["prompt"] = ox.escape_html(prompt)
|
||||||
ai.data["firstframe"] = " ".join([ox.toAZ(ff.id) for ff in first_frames])
|
ai.data["firstframe"] = " ".join([ff.get_id() for ff in first_frames])
|
||||||
ai.data["model"] = status["model"]
|
ai.data["model"] = status["model"]
|
||||||
ai.data["seed"] = seed
|
ai.data["seed"] = seed
|
||||||
ai.save()
|
ai.save()
|
||||||
|
|
@ -1137,22 +1223,6 @@ def add_tag(item, tag):
|
||||||
item.data['tags'].append(tag)
|
item.data['tags'].append(tag)
|
||||||
item.save()
|
item.save()
|
||||||
|
|
||||||
def process_motion_firstframe(character="P1", keep=False):
|
|
||||||
l = itemlist.models.List.objects.get(name='Motion-Firstframe')
|
|
||||||
for i in l.items.all():
|
|
||||||
ai = Item.objects.filter(data__type__icontains='ai').filter(data__title=i.data['title'])
|
|
||||||
if ai.exists() or 'ai-failed' in i.data.get('tags', []):
|
|
||||||
print('>> skip', i)
|
|
||||||
continue
|
|
||||||
print(i)
|
|
||||||
try:
|
|
||||||
replace_character_motion_control(i, character, keep=keep)
|
|
||||||
except:
|
|
||||||
i.refresh_from_db()
|
|
||||||
add_tag(i, 'ai-failed')
|
|
||||||
print('>> failed', i)
|
|
||||||
|
|
||||||
|
|
||||||
def extract_firstframe(character='P1'):
|
def extract_firstframe(character='P1'):
|
||||||
for item in Item.objects.filter(data__type__icontains="source"):
|
for item in Item.objects.filter(data__type__icontains="source"):
|
||||||
if 'ai-failed' in item.data.get('tags', []):
|
if 'ai-failed' in item.data.get('tags', []):
|
||||||
|
|
@ -1165,43 +1235,43 @@ def extract_firstframe(character='P1'):
|
||||||
item.refresh_from_db()
|
item.refresh_from_db()
|
||||||
add_tag(item, 'ai-failed')
|
add_tag(item, 'ai-failed')
|
||||||
|
|
||||||
def process_reshoot_firstframe():
|
def process_reshoot_firstframe(character='P1'):
|
||||||
|
position = 0
|
||||||
l = itemlist.models.List.objects.get(name='Reshoot-Firstframe')
|
l = itemlist.models.List.objects.get(name='Reshoot-Firstframe')
|
||||||
for i in l.items.all():
|
for item in l.items.all():
|
||||||
if i.sort.duration > 30: continue
|
if 'ai-failed' in item.data.get('tags', []):
|
||||||
if i.public_id == 'HZ': continue
|
print('>> skip', item)
|
||||||
if i.documents.all().count():
|
continue
|
||||||
ai = Item.objects.filter(data__type__icontains='ai').filter(data__title=i.data['title'])
|
if item.sort.duration > 30:
|
||||||
if ai.exists() or 'ai-failed' in i.data.get('tags', []):
|
reshoot_item_segments(item, character)
|
||||||
print('>> skip', i)
|
else:
|
||||||
continue
|
cid = get_character_document(character).get_id()
|
||||||
first_frame = i.documents.all().order_by('-created').first()
|
first_frame = item.documents.filter(
|
||||||
|
data__character=cid, data__position=position
|
||||||
|
).order_by('-created').first()
|
||||||
if not first_frame:
|
if not first_frame:
|
||||||
first_frame = replace_character(i, 'P1', 0)
|
first_frame = replace_character(item, character, position)
|
||||||
print(i, first_frame, i.documents.all().count())
|
if first_frame.items.filter(data__type__icontains='ai:').exists():
|
||||||
|
continue
|
||||||
|
print(item, first_frame)
|
||||||
try:
|
try:
|
||||||
reshoot_item(i, first_frame=first_frame)
|
reshoot_item(item, first_frame=first_frame)
|
||||||
except:
|
except:
|
||||||
add_tag(i, 'ai-failed')
|
add_tag(item, 'ai-failed')
|
||||||
print('>> failed', i)
|
print('>> failed', item)
|
||||||
|
|
||||||
def process_motion_firstframe():
|
def process_motion_firstframe(character="P1", keep=False):
|
||||||
l = itemlist.models.List.objects.get(name='Motion-Firstframe')
|
l = itemlist.models.List.objects.get(name='Motion-Firstframe')
|
||||||
for i in l.items.all():
|
for item in l.items.all():
|
||||||
if i.sort.duration > 30: continue
|
ai = Item.objects.filter(data__type__icontains='ai').filter(data__title=item.data['title'])
|
||||||
if i.public_id == 'HZ': continue
|
if ai.exists() or 'ai-failed' in item.data.get('tags', []):
|
||||||
if i.documents.all().count():
|
print('>> skip', item)
|
||||||
ai = Item.objects.filter(data__type__icontains='ai').filter(data__title=i.data['title'])
|
continue
|
||||||
if ai.exists() or 'ai-failed' in i.data.get('tags', []):
|
print(i)
|
||||||
print('>> skip', i)
|
try:
|
||||||
continue
|
replace_character_motion_control(item, character, keep=keep)
|
||||||
first_frame = i.documents.all().order_by('-created').first()
|
except:
|
||||||
if not first_frame:
|
item.refresh_from_db()
|
||||||
first_frame = replace_character(i, 'P1', 0)
|
add_tag(item, 'ai-failed')
|
||||||
print(i, first_frame, i.documents.all().count())
|
print('>> failed', item)
|
||||||
try:
|
|
||||||
replace_character_motion_control(i, first_frame)
|
|
||||||
except:
|
|
||||||
add_tag(i, 'ai-failed')
|
|
||||||
print('>> failed', i)
|
|
||||||
|
|
||||||
|
|
|
||||||
15
render.py
15
render.py
|
|
@ -84,7 +84,7 @@ def compose(clips, fragment, target=150, base=1024, voice_over=None, options=Non
|
||||||
selected_clips = []
|
selected_clips = []
|
||||||
|
|
||||||
tags = []
|
tags = []
|
||||||
while selected_clips_length < target:
|
while selected_clips_length < target * 1.1:
|
||||||
if not tags:
|
if not tags:
|
||||||
tags = fragment["tags"].copy()
|
tags = fragment["tags"].copy()
|
||||||
tag = random_choice(seq, tags, pop=True)
|
tag = random_choice(seq, tags, pop=True)
|
||||||
|
|
@ -132,18 +132,18 @@ def compose(clips, fragment, target=150, base=1024, voice_over=None, options=Non
|
||||||
next_length = length + clip['duration']
|
next_length = length + clip['duration']
|
||||||
if target - next_length < -target*0.1:
|
if target - next_length < -target*0.1:
|
||||||
break
|
break
|
||||||
length += int(clip['duration'] * fps) / fps
|
clip_duration = int(clip['duration'] * fps) / fps
|
||||||
|
length += clip_duration
|
||||||
|
|
||||||
# 50/50 source or ai
|
# 50/50 source or ai
|
||||||
src = clip['source']
|
src = clip['source']
|
||||||
audio = clip['source']
|
audio = clip['source']
|
||||||
# select ai if we have one
|
# select ai if we have one
|
||||||
if 'ai' in clip:
|
if 'ai' in clip and clip.get("use_ai"):
|
||||||
if clip["use_ai"]:
|
src = random_choice(seq, list(clip['ai'].values()), False)
|
||||||
src = random_choice(seq, list(clip['ai'].values()), False)
|
|
||||||
|
|
||||||
print('%07.3f-%07.3f %07.3f %s (%s)' % (
|
print('%07.3f-%07.3f %07.3f %s (%s)' % (
|
||||||
length-clip['duration'],
|
length-clip_duration,
|
||||||
length,
|
length,
|
||||||
clip['duration'],
|
clip['duration'],
|
||||||
os.path.basename(clip['source']),
|
os.path.basename(clip['source']),
|
||||||
|
|
@ -196,6 +196,9 @@ def compose(clips, fragment, target=150, base=1024, voice_over=None, options=Non
|
||||||
if not clips:
|
if not clips:
|
||||||
print("not enough clips, also consider last clip")
|
print("not enough clips, also consider last clip")
|
||||||
clips = all_clips.copy()
|
clips = all_clips.copy()
|
||||||
|
for clip in clips:
|
||||||
|
if "ai" in clip:
|
||||||
|
clip["use_ai"] = True
|
||||||
|
|
||||||
scene_duration = int(get_scene_duration(scene) * fps)
|
scene_duration = int(get_scene_duration(scene) * fps)
|
||||||
voice_overs = []
|
voice_overs = []
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue