Added thumbnails for 8.Kyu
This commit is contained in:
@@ -1,50 +1,86 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"source": "http://download.m-m-sports.com/extras/judo_guertelpruefung/1_8%20fallrw.mp4",
|
"source": "http://download.m-m-sports.com/extras/judo_guertelpruefung/1_8%20fallrw.mp4",
|
||||||
"target": "videos/8terKyu/Ukemi/Ushiro.webm"
|
"target": "videos/8terKyu/Ukemi/Ushiro.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "34.760"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "http://mmurl.de/judo02",
|
"source": "http://mmurl.de/judo02",
|
||||||
"target": "videos/8terKyu/Ukemi/Yoko.webm"
|
"target": "videos/8terKyu/Ukemi/Yoko.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "23.320"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "http://mmurl.de/judo03",
|
"source": "http://mmurl.de/judo03",
|
||||||
"target": "videos/8terKyu/NageWaza/OGoshiUkiGoshi.webm"
|
"target": "videos/8terKyu/NageWaza/OGoshiUkiGoshi.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "42.000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "http://mmurl.de/judo04",
|
"source": "http://mmurl.de/judo04",
|
||||||
"target": "videos/8terKyu/NageWaza/BeidbeinigeEindrehtechnik.webm"
|
"target": "videos/8terKyu/NageWaza/BeidbeinigeEindrehtechnik.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "27.760"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "http://mmurl.de/judo05",
|
"source": "http://mmurl.de/judo05",
|
||||||
"target": "videos/8terKyu/NageWaza/OSotoOtoshi.webm"
|
"target": "videos/8terKyu/NageWaza/OSotoOtoshi.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "12.920"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "http://mmurl.de/judo06",
|
"source": "http://mmurl.de/judo06",
|
||||||
"target": "videos/8terKyu/OsaeKomiWaza/KesaGatame.webm"
|
"target": "videos/8terKyu/OsaeKomiWaza/KesaGatame.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "11.800"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "http://mmurl.de/judo07",
|
"source": "http://mmurl.de/judo07",
|
||||||
"target": "videos/8terKyu/OsaeKomiWaza/MuneGatame.webm"
|
"target": "videos/8terKyu/OsaeKomiWaza/MuneGatame.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "14.240"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "http://mmurl.de/judo08",
|
"source": "http://mmurl.de/judo08",
|
||||||
"target": "videos/8terKyu/TachiWaza/EindrehtechnikUkeSchiebt.webm"
|
"target": "videos/8terKyu/TachiWaza/EindrehtechnikUkeSchiebt.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "28.920"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "http://mmurl.de/judo09",
|
"source": "http://mmurl.de/judo09",
|
||||||
"target": "videos/8terKyu/TachiWaza/OSotoOtoshiUkeZieht.webm"
|
"target": "videos/8terKyu/TachiWaza/OSotoOtoshiUkeZieht.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "14.440"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "http://mmurl.de/judo10",
|
"source": "http://mmurl.de/judo10",
|
||||||
"target": "videos/8terKyu/TachiWaza/UebergangStandBoden.webm"
|
"target": "videos/8terKyu/TachiWaza/UebergangStandBoden.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "1:08.560"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "http://mmurl.de/judo11",
|
"source": "http://mmurl.de/judo11",
|
||||||
"target": "videos/8terKyu/NeWaza/BefreiungOsaeKomi.webm"
|
"target": "videos/8terKyu/NeWaza/BefreiungOsaeKomi.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "1:02.680"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "http://mmurl.de/judo12",
|
"source": "http://mmurl.de/judo12",
|
||||||
"target": "videos/8terKyu/Randori/Randori.webm"
|
"target": "videos/8terKyu/Randori/Randori.webm",
|
||||||
|
"poster":{
|
||||||
|
"timeIndex": "35.400"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -9,16 +9,41 @@ import sys
|
|||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
def generate_thumbnail(in_filename, out_filename, time, height):
|
||||||
|
try:
|
||||||
|
(
|
||||||
|
ffmpeg
|
||||||
|
.input(in_filename, ss=time)
|
||||||
|
.filter('scale', -2, height)
|
||||||
|
.output(out_filename, vframes=1)
|
||||||
|
.overwrite_output()
|
||||||
|
.run(capture_stdout=True, capture_stderr=True)
|
||||||
|
)
|
||||||
|
except ffmpeg.Error as e:
|
||||||
|
print(e.stderr.decode(), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# setting width and height from hardcoded defaults -> configured defaults -> clip
|
||||||
|
def getDimensions(config, clip):
|
||||||
|
h = config['height'] if 'height' in config else 480
|
||||||
|
w = config['width'] if 'width' in config else -2
|
||||||
|
if 'scale' in clip:
|
||||||
|
h = clip['scale']['h'] if 'h' in clip['scale'] else h
|
||||||
|
w = clip['scale']['w'] if 'w' in clip['scale'] else w
|
||||||
|
|
||||||
|
return h, w
|
||||||
|
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
'vcodec': "vp9",
|
'vcodec': "vp9",
|
||||||
'acodec': "libopus"
|
'acodec': "libopus",
|
||||||
|
'height': 480,
|
||||||
|
'quality': "best",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
argParser = argparse.ArgumentParser()
|
argParser = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
|
||||||
jsonFileName = sys.argv[1]
|
jsonFileName = sys.argv[1]
|
||||||
|
|
||||||
clipDict = {}
|
clipDict = {}
|
||||||
@@ -28,7 +53,7 @@ with open(jsonFileName) as jf:
|
|||||||
ydl_opts = {"outtmpl": "%(id)s"}
|
ydl_opts = {"outtmpl": "%(id)s"}
|
||||||
|
|
||||||
for clip in clipDict:
|
for clip in clipDict:
|
||||||
# create the directories so ffmped doesn't complain
|
# create the directories so ffmpeg doesn't complain
|
||||||
try:
|
try:
|
||||||
outputDir = os.path.dirname(clip['target'])
|
outputDir = os.path.dirname(clip['target'])
|
||||||
os.makedirs(outputDir)
|
os.makedirs(outputDir)
|
||||||
@@ -41,20 +66,22 @@ for clip in clipDict:
|
|||||||
ydl.download([clip['source']])
|
ydl.download([clip['source']])
|
||||||
|
|
||||||
if infoDict is not None:
|
if infoDict is not None:
|
||||||
if 'from' in clip and 'to' in clip:
|
# @todo This is a very bad hack because the outtmpl options doesn't seem to be working if the file gets reencoded
|
||||||
stream = ffmpeg.input(
|
inputFilename = glob.glob(infoDict['id']+"*")[0]
|
||||||
# @todo This is a very bad hack because the outtmpl options doesn't seem to be working if the file gets reencoded
|
|
||||||
glob.glob(infoDict['id']+"*")[0],
|
|
||||||
ss=clip['from'],
|
|
||||||
to=clip['to'],
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
stream = ffmpeg.input(
|
|
||||||
glob.glob(infoDict['id']+"*")[0],
|
|
||||||
)
|
|
||||||
|
|
||||||
video = stream.video
|
# generate preview image for the video
|
||||||
audio = stream.audio
|
if 'poster' in clip:
|
||||||
|
generate_thumbnail(inputFilename, os.path.splitext(clip['target'])[0]+".jpg", clip['poster']['timeIndex'], h )
|
||||||
|
|
||||||
|
kwArgs = {}
|
||||||
|
if 'from' in clip:
|
||||||
|
kwArgs['ss'] = clip['from']
|
||||||
|
if 'to' in clip:
|
||||||
|
kwArgs['to'] = clip['to']
|
||||||
|
|
||||||
|
stream = ffmpeg.input( inputFilename, **kwArgs)
|
||||||
|
|
||||||
|
video, audio = stream.video, stream.audio
|
||||||
|
|
||||||
if 'crop' in clip:
|
if 'crop' in clip:
|
||||||
stream = ffmpeg.filter(stream,
|
stream = ffmpeg.filter(stream,
|
||||||
@@ -65,12 +92,7 @@ for clip in clipDict:
|
|||||||
h=clip['crop']['h']
|
h=clip['crop']['h']
|
||||||
)
|
)
|
||||||
|
|
||||||
h = 480
|
h, w = getDimensions(config, clip)
|
||||||
w = -2
|
|
||||||
if 'scale' in clip:
|
|
||||||
h = clip['scale']['h'] if 'h' in clip['scale'] else 480
|
|
||||||
w = clip['scale']['w'] if 'w' in clip['scale'] else -2
|
|
||||||
stream = ffmpeg.filter(stream, "scale", height=h, width=w )
|
|
||||||
|
|
||||||
stream = ffmpeg.output(stream,
|
stream = ffmpeg.output(stream,
|
||||||
clip['target'],
|
clip['target'],
|
||||||
@@ -82,7 +104,7 @@ for clip in clipDict:
|
|||||||
# "b:v":"276k", "minrate":"138k", "maxrate":"400k", # x360
|
# "b:v":"276k", "minrate":"138k", "maxrate":"400k", # x360
|
||||||
"b:v":"512k", "minrate":"256k", "maxrate":"742k", # x480 LQ
|
"b:v":"512k", "minrate":"256k", "maxrate":"742k", # x480 LQ
|
||||||
# "b:v":"750k", "minrate":"375k", "maxrate":"1088k", # x480 MQ
|
# "b:v":"750k", "minrate":"375k", "maxrate":"1088k", # x480 MQ
|
||||||
"quality":"good",
|
"quality": config['quality'] if 'quality' in config else "best",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
@@ -110,12 +132,7 @@ for clip in clipDict:
|
|||||||
h=clip['crop']['h']
|
h=clip['crop']['h']
|
||||||
)
|
)
|
||||||
|
|
||||||
h = 480
|
h, w = getDimensions(config, clip)
|
||||||
w = -2
|
|
||||||
if 'scale' in clip:
|
|
||||||
h = clip['scale']['h'] if 'h' in clip['scale'] else 480
|
|
||||||
w = clip['scale']['w'] if 'w' in clip['scale'] else -2
|
|
||||||
stream = ffmpeg.filter(stream, "scale", height=h, width=w )
|
|
||||||
|
|
||||||
stream = ffmpeg.output(stream, audio,
|
stream = ffmpeg.output(stream, audio,
|
||||||
clip['target'],
|
clip['target'],
|
||||||
@@ -124,8 +141,10 @@ for clip in clipDict:
|
|||||||
# "an":None,
|
# "an":None,
|
||||||
"y":None,
|
"y":None,
|
||||||
"pass":"2",
|
"pass":"2",
|
||||||
"b:v":"512k", "minrate":"375k", "maxrate":"1088k",
|
# "b:v":"276k", "minrate":"138k", "maxrate":"400k", # x360
|
||||||
"quality":"good",
|
"b:v":"512k", "minrate":"256k", "maxrate":"742k", # x480 LQ
|
||||||
|
# "b:v":"750k", "minrate":"375k", "maxrate":"1088k", # x480 MQ
|
||||||
|
"quality": config['quality'] if 'quality' in config else "best",
|
||||||
"acodec": config['acodec'],
|
"acodec": config['acodec'],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -133,6 +152,5 @@ for clip in clipDict:
|
|||||||
ffmpeg.run(stream)
|
ffmpeg.run(stream)
|
||||||
except:
|
except:
|
||||||
print(infoDict)
|
print(infoDict)
|
||||||
|
|
||||||
|
exit(-1)
|
||||||
#640x480p @ 24,25,30 512 (LQ), 750 (MQ) 256 (LQ) 375 (MQ) 742 (LQ) 1088 (MQ)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user