Compare commits
2 commits
eb1ea250eb
...
959d1f5408
Author | SHA1 | Date | |
---|---|---|---|
959d1f5408 | |||
ad33ce2c41 |
2 changed files with 66 additions and 23 deletions
51
edit.py
51
edit.py
|
@ -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', []):
|
||||||
|
|
38
ffmpeg.py
38
ffmpeg.py
|
@ -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'
|
||||||
|
|
Loading…
Reference in a new issue