Added thumbnails for 8.Kyu

This commit is contained in:
marko
2022-02-19 10:33:14 +01:00
parent acf6c09b0d
commit 975c88dee6
2 changed files with 100 additions and 46 deletions

View File

@@ -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"
}
} }
] ]

View File

@@ -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)