diff --git a/build.py b/build.py new file mode 100755 index 0000000..6eda9f8 --- /dev/null +++ b/build.py @@ -0,0 +1,113 @@ +#! /usr/bin/env python3 + +import os +import subprocess + +SECTIONS = { + 'drift': 'Drift', + 'fs': 'FreeStyle', + 'k': 'K projects', + 'lol': 'LOL', + 'pf': 'Press Forward', + 'ta': 'Time Attack', + 'trial': 'Trial', +} + + +def card(name, web, raw): + return f'''\ +
+ +
+{name} +
+''' + + +def a(href, text, active=False): + html = ['{text}') + return str().join(html) + + +def nav(sections, active): + html = ['') + return str().join(html) + + +def body(sections): + html = [] + for _, section in sorted(sections.items()): + html.append(f'
') + html.append(section['content']) + html.append('
') + return str().join(html) + + +def html(body): + return f'''\ + + + + + +TrackMania vidz + + + + + +{body} + + + +''' + + +def main(): + file = os.path.realpath(__file__) + root = os.path.dirname(file) + raw_root = os.path.join(root, 'raw') + web_root = os.path.join(root, 'web') + _, categories, _ = next(os.walk(raw_root)) + sections = { + ' ': {'id': 'home', 'label': '⋅', 'content': str()}, + } + for category in categories: + section = { + 'id': category, + 'label': SECTIONS.get(category, category), + } + content = [] + raw_category = os.path.join(raw_root, category) + videos = {} + for directory, directories, files in os.walk(raw_category): + for file in files: + relative = os.path.relpath(directory, raw_root) + name, _ = os.path.splitext(file) + raw_file = os.path.join('raw', relative, file) + web_file = os.path.join('web', relative, f'{name}.mp4') + videos[name] = [web_file, raw_file] + for name, files in sorted(videos.items()): + web_file, raw_file = files + content.append(card(name, web_file, raw_file)) + section['content'] = os.linesep.join([ + '
', os.linesep.join(content), '
']) + sections[category] = section + for id, section in sections.items(): + section['content'] = nav(sections, id) + section['content'] + index = os.path.join(root, 'index.html') + with open(index, 'w') as i: + i.write(html(body(sections))) + + +if __name__ == '__main__': + main() diff --git a/encode.py b/encode.py new file mode 100755 index 0000000..ae04b98 --- /dev/null +++ b/encode.py @@ -0,0 +1,49 @@ +#! /usr/bin/env python3 + +import os +import subprocess + + +def encode(input_file, output_file): + output_directory = os.path.dirname(output_file) + os.makedirs(output_directory, exist_ok=True) + if not os.path.exists(output_file): + subprocess.call([ + 'ffmpeg', + '-i', input_file, + '-codec:a', 'libopus', + '-b:a', '128K', + '-codec:v', 'libx264', + '-preset', 'veryslow', + '-qp', '23', + '-movflags', '+faststart', + '-pix_fmt', 'yuv420p', + output_file + ]) + + +def main(): + file = os.path.realpath(__file__) + root = os.path.dirname(file) + raw_root = os.path.join(root, 'raw') + web_root = os.path.join(root, 'web') + print(f'← {raw_root}') + print(f'→ {web_root}') + tasks = [] + for directory, directories, files in os.walk(raw_root): + for file in files: + relative_directory = os.path.relpath(directory, raw_root) + name, ext = os.path.splitext(file) + relative_name = os.path.join(relative_directory, name) + tasks.append((relative_name, ext)) + for relative_name, ext in sorted(tasks): + raw_file = os.path.join(raw_root, f'{relative_name}{ext}') + web_file = os.path.join(web_root, f'{relative_name}.mp4') + print() + print(f'← {raw_file}') + print(f'→ {web_file}') + encode(raw_file, web_file) + + +if __name__ == '__main__': + main() diff --git a/index.css b/index.css new file mode 100644 index 0000000..7eca81c --- /dev/null +++ b/index.css @@ -0,0 +1,90 @@ +@viewport { +width: device-width; +zoom: 1; +} + +/* +* { border: 1px solid; } +/* +header { background: #800000; } +nav { background: #008000; } +section { background: #000080; } +/**/ + +* { +box-sizing: border-box; +//margin: 0; +//padding: 0; +} + +html { +background: rgb(0,0,0); +color: rgb(160,160,160); +font-family: sans; +} + +body { +margin: 0 auto; +position: relative; +} + +section { +display: none; +min-height: 100vh; +padding: 1em 1vw 1vh 1vw; +position: absolute; +top: 0; +width: 100%; +} +#home,section:target { +display: block; +} + +nav { +display: flex; +flex-wrap: wrap; +} + +a { +text-decoration: none; +} + +nav a { +background: linear-gradient(rgba(64,64,64,1), rgba(64,64,64,0)); +border-color: rgb(128,128,128); +border-radius: .5em; +border-style: solid; +border-width: 1px 1px 0 1px; +#color: rgb(128,128,0); +font-weight: bold; +padding: .25em .5em; +//transition: all .5s; +} +nav a.active { +background: linear-gradient(rgba(128,128,128,1), rgba(128,128,128,0)); +} + +a { +color: rgb(0,192,192); +} +a:hover { +color: rgb(192,0,0); +} +a:visited { +color: rgb(0,160,160); +} + +.cards { +display: flex; +flex-wrap: wrap; +} + +.card { +background-color: #101010; +border: 1px solid; +border-radius: .5em; +color: #404040; +margin: .1em; +padding: .5em .6em .5 em .25em; +vertical-align: top; +}