switch to .ass subtitles to adjust per language font/size
This commit is contained in:
parent
b1db77de53
commit
790ae53095
2 changed files with 277 additions and 180 deletions
|
|
@ -1,31 +1,6 @@
|
|||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from collections import defaultdict
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
|
||||
import item.models
|
||||
import itemlist.models
|
||||
|
||||
from ...render import get_srt
|
||||
|
||||
|
||||
def resolve_roman(s):
|
||||
extra = re.compile(r'^\d+(.*?)$').findall(s)
|
||||
if extra:
|
||||
extra = extra[0].lower()
|
||||
new = {
|
||||
'i': '1', 'ii': '2', 'iii': '3', 'iv': '4', 'v': '5',
|
||||
'vi': '6', 'vii': 7, 'viii': '8', 'ix': '9', 'x': '10'
|
||||
}.get(extra, extra)
|
||||
return s.replace(extra, new)
|
||||
return s
|
||||
|
||||
def format_duration(duration, fps):
|
||||
return float('%0.5f' % (round(duration * fps) / fps))
|
||||
from ...render import generate_clips
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
|
@ -37,120 +12,4 @@ class Command(BaseCommand):
|
|||
parser.add_argument('--censored', action='store', dest='censored', default=None, help='censor items from list')
|
||||
|
||||
def handle(self, **options):
|
||||
prefix = options['prefix']
|
||||
lang = options["lang"]
|
||||
if lang:
|
||||
lang = lang.split(',')
|
||||
tlang = lang[1:]
|
||||
lang = lang[0]
|
||||
else:
|
||||
tlang = None
|
||||
if lang == "en":
|
||||
lang = None
|
||||
if options['censored']:
|
||||
censored_list = itemlist.models.List.get(options["censored"])
|
||||
censored = list(censored_list.get_items(censored_list.user).all().values_list('public_id', flat=True))
|
||||
clips = []
|
||||
for i in item.models.Item.objects.filter(sort__type='original'):
|
||||
original_target = ""
|
||||
qs = item.models.Item.objects.filter(data__title=i.data['title']).exclude(id=i.id)
|
||||
if qs.count() >= 1:
|
||||
clip = {}
|
||||
durations = []
|
||||
for e in item.models.Item.objects.filter(data__title=i.data['title']):
|
||||
if 'type' not in e.data:
|
||||
print("ignoring invalid video %s (no type)" % e)
|
||||
continue
|
||||
if not e.files.filter(selected=True).exists():
|
||||
continue
|
||||
source = e.files.filter(selected=True)[0].data.path
|
||||
ext = os.path.splitext(source)[1]
|
||||
type_ = e.data['type'][0].lower()
|
||||
target = os.path.join(prefix, type_, i.data['title'] + ext)
|
||||
os.makedirs(os.path.dirname(target), exist_ok=True)
|
||||
if os.path.islink(target):
|
||||
os.unlink(target)
|
||||
os.symlink(source, target)
|
||||
if type_ == "original":
|
||||
original_target = target
|
||||
if options['censored'] and e.public_id in censored:
|
||||
clip[type_ + "_censored"] = target
|
||||
target = '/srv/t_for_time/censored.mp4'
|
||||
clip[type_] = target
|
||||
durations.append(e.files.filter(selected=True)[0].duration)
|
||||
clip["duration"] = min(durations)
|
||||
if not clip["duration"]:
|
||||
print('!!', durations, clip)
|
||||
continue
|
||||
cd = format_duration(clip["duration"], 24)
|
||||
#if cd != clip["duration"]:
|
||||
# print(clip["duration"], '->', cd, durations, clip)
|
||||
clip["duration"] = cd
|
||||
clip['tags'] = i.data.get('tags', [])
|
||||
clip['editingtags'] = i.data.get('editingtags', [])
|
||||
name = os.path.basename(original_target)
|
||||
seqid = re.sub(r"Hotel Aporia_(\d+)", "S\\1_", name)
|
||||
seqid = re.sub(r"Night March_(\d+)", "S\\1_", seqid)
|
||||
seqid = re.sub(r"_(\d+)H_(\d+)", "_S\\1\\2_", seqid)
|
||||
seqid = seqid.split('_')[:2]
|
||||
seqid = [b[1:] if b[0] in ('B', 'S') else '0' for b in seqid]
|
||||
seqid[1] = resolve_roman(seqid[1])
|
||||
seqid[1] = ''.join([b for b in seqid[1] if b.isdigit()])
|
||||
if not seqid[1]:
|
||||
seqid[1] = '0'
|
||||
try:
|
||||
clip['seqid'] = int(''.join(['%06d' % int(b) for b in seqid]))
|
||||
except:
|
||||
print(name, seqid, 'failed')
|
||||
raise
|
||||
if "original" in clip and "foreground" in clip and "background" in clip:
|
||||
clips.append(clip)
|
||||
elif "original" in clip and "animation" in clip:
|
||||
clips.append(clip)
|
||||
else:
|
||||
print("ignoring incomplete video", i)
|
||||
|
||||
with open(os.path.join(prefix, 'clips.json'), 'w') as fd:
|
||||
json.dump(clips, fd, indent=2, ensure_ascii=False)
|
||||
|
||||
print("using", len(clips), "clips")
|
||||
|
||||
voice_over = defaultdict(dict)
|
||||
for vo in item.models.Item.objects.filter(
|
||||
data__type__contains="Voice Over",
|
||||
):
|
||||
fragment_id = int(vo.get('title').split('_')[0])
|
||||
source = vo.files.filter(selected=True)[0]
|
||||
batch = vo.get('batch')[0].replace('Text-', '')
|
||||
src = source.data.path
|
||||
target = os.path.join(prefix, 'voice_over', batch, '%s.wav' % fragment_id)
|
||||
os.makedirs(os.path.dirname(target), exist_ok=True)
|
||||
if os.path.islink(target):
|
||||
os.unlink(target)
|
||||
os.symlink(src, target)
|
||||
subs = []
|
||||
for sub in vo.annotations.filter(layer="subtitles", languages=lang).exclude(value="").order_by("start"):
|
||||
sdata = get_srt(sub, lang=tlang)
|
||||
subs.append(sdata)
|
||||
voice_over[fragment_id][batch] = {
|
||||
"src": target,
|
||||
"duration": format_duration(source.duration, 24),
|
||||
"subs": subs
|
||||
}
|
||||
with open(os.path.join(prefix, 'voice_over.json'), 'w') as fd:
|
||||
json.dump(voice_over, fd, indent=2, ensure_ascii=False)
|
||||
|
||||
if options['censored']:
|
||||
censored_mp4 = '/srv/t_for_time/censored.mp4'
|
||||
if not os.path.exists(censored_mp4):
|
||||
cmd = [
|
||||
"ffmpeg",
|
||||
"-nostats", "-loglevel", "error",
|
||||
"-f", "lavfi",
|
||||
"-i", "color=color=white:size=1920x1080:rate=24",
|
||||
"-t", "3600",
|
||||
"-c:v", "libx264",
|
||||
"-pix_fmt", "yuv420p",
|
||||
censored_mp4
|
||||
]
|
||||
subprocess.call(cmd)
|
||||
return generate_clips(options)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue