Compare commits

...

2 commits

Author SHA1 Message Date
j
959d1f5408 make title 2024-05-22 10:46:32 +02:00
j
ad33ce2c41 fix subtitle rendering 2024-05-22 10:46:26 +02:00
2 changed files with 66 additions and 23 deletions

51
edit.py
View file

@ -1,13 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from argparse import ArgumentParser from argparse import ArgumentParser
from glob import glob
import getpass import getpass
import hashlib
import json import json
import math import math
import os import os
import subprocess
import sys import sys
import urllib.parse import urllib.parse
import urllib.request import urllib.request
from glob import glob
import ox import ox
import ox.web.auth import ox.web.auth
@ -20,7 +22,6 @@ pandora_client_config = {}
use_local = False use_local = False
if os.path.exists('files.json'): if os.path.exists('files.json'):
files = json.load(open('files.json')) files = json.load(open('files.json'))
else: else:
@ -104,6 +105,8 @@ def get_pandora_media_path(oshash):
def cache_clips(api, videos, use_source=False, use_pandora=False): def cache_clips(api, videos, use_source=False, use_pandora=False):
for clip in videos: for clip in videos:
if clip.get("title"):
continue
out = '%s/%s.mp4' % (render, clip['oshash']) out = '%s/%s.mp4' % (render, clip['oshash'])
if 'path' in clip: if 'path' in clip:
clip['src'] = clip['path'] clip['src'] = clip['path']
@ -124,6 +127,38 @@ def cache_clips(api, videos, use_source=False, use_pandora=False):
print(url, out) print(url, out)
api.save_url(url, out) api.save_url(url, out)
def make_title(title):
from PIL import Image, ImageFont, ImageDraw
title_mp4 = "cache/title_%s.mp4" % hashlib.sha1(title.encode()).hexdigest()
title_png = title_mp4.replace('.mp4', '.png')
if not os.path.exists(title_mp4):
width = 852
height = 480
image = Image.new("RGB", (width, height), "black")
font = ImageFont.truetype("/usr/share/fonts/truetype/roboto/unhinted/RobotoTTF/Roboto-Regular.ttf", size=30)
draw = ImageDraw.Draw(image)
_, _, font_width, font_height = font.getbbox(title)
new_width = (width - font_width) / 2
new_height = (height - font_height) / 2
draw.text((new_width, new_height), title, font=font)
image.save(title_png)
cmd = [
'ffmpeg', '-r', '25',
'-i', title_png, '-t', '5',
'-pix_fmt', 'yuv420p',
title_mp4
]
subprocess.call(cmd)
clip = {
"title": title,
"in": 0,
"out": 5,
"duration": 5,
"volume": 1.0,
"path": title_mp4
}
return clip
if __name__ == '__main__': if __name__ == '__main__':
usage = "usage: %(prog)s [options] edit-url" usage = "usage: %(prog)s [options] edit-url"
@ -134,6 +169,8 @@ if __name__ == '__main__':
help="source, local or site", default='site') help="source, local or site", default='site')
parser.add_argument('-r', '--resolution', dest='stream_resolution', type=int, parser.add_argument('-r', '--resolution', dest='stream_resolution', type=int,
help="resolution of streams to download i.e. 480, 240, 96 default 480", default=480) help="resolution of streams to download i.e. 480, 240, 96 default 480", default=480)
parser.add_argument('-t', '--title', dest='title', type=str,
help="title", default="")
parser.add_argument('-c', '--config', dest='config', parser.add_argument('-c', '--config', dest='config',
help='config.json containing config', help='config.json containing config',
default='~/.ox/client.json') default='~/.ox/client.json')
@ -199,7 +236,15 @@ if __name__ == '__main__':
videos = [] videos = []
subtitles = [] subtitles = []
position = 0 position = 0
for clip in sort_clips(edit, sort_by): clips = sort_clips(edit, sort_by)
if opts.title:
clips.insert(0, make_title(opts.title))
for clip in clips:
if clip.get("title"):
videos.append(clip)
position += clip['duration']
position = math.ceil(position / (1/25)) * 1/25
continue
clip_out = position + clip['duration'] clip_out = position + clip['duration']
clip_subtitles = [] clip_subtitles = []
for sub in clip['layers'].get('subtitles', []): for sub in clip['layers'].get('subtitles', []):

View file

@ -11,6 +11,22 @@ def run(cmd):
#print(' '.join('"%s"' % c for c in cmd)) #print(' '.join('"%s"' % c for c in cmd))
subprocess.call(cmd) subprocess.call(cmd)
def add_subtitles(subtitles, clip, position, duration):
if clip.get('subtitles'):
if isinstance(clip['subtitles'], list):
for sub in clip['subtitles']:
subtitles.append({
'in': position + sub['in'],
'out': position + sub['out'],
'value': sub['value']
})
else:
subtitles.append({
'in': position,
'out': position + duration,
'value': clip['subtitles']
})
usage = "usage: %(prog)s [options] edit.json" usage = "usage: %(prog)s [options] edit.json"
parser = ArgumentParser(usage=usage) parser = ArgumentParser(usage=usage)
@ -62,12 +78,7 @@ for clip in edit:
src_duration = clip['out']-clip['in'] src_duration = clip['out']-clip['in']
if abs(src_duration-duration) > 1: if abs(src_duration-duration) > 1:
print(clip.get('annotation', clip['item']), 'expected', src_duration, 'got', duration, out) print(clip.get('annotation', clip['item']), 'expected', src_duration, 'got', duration, out)
if clip.get('subtitles'): add_subtitles(subtitles, clip, position, duration)
subtitles.append({
'in': position,
'out': position+duration,
'value': clip['subtitles']
})
position += duration position += duration
continue continue
src_info = ox.avinfo(clip['path']) src_info = ox.avinfo(clip['path'])
@ -142,20 +153,7 @@ for clip in edit:
src_duration = clip['out']-clip['in'] src_duration = clip['out']-clip['in']
if abs(src_duration-duration) > 1: if abs(src_duration-duration) > 1:
print(clip.get('annotation', clip['item']), 'expected', src_duration, 'got', duration, out) print(clip.get('annotation', clip['item']), 'expected', src_duration, 'got', duration, out)
if clip.get('subtitles'): add_subtitles(subtitles, clip, position, duration)
if isinstance(clip['subtitles'], list):
for sub in clip['subtitles']:
subtitles.append({
'in': position + sub['in'],
'out': position + sub['out'],
'value': sub['value']
})
else:
subtitles.append({
'in': position,
'out': position + duration,
'value': clip['subtitles']
})
position += duration position += duration
txt = output + '.txt' txt = output + '.txt'