Compare commits

...

10 commits

Author SHA1 Message Date
904ff277ad b:a 2023-01-14 11:50:01 +01:00
3366c72ac1 cards,css 2023-01-11 10:25:19 +01:00
47aa5ec591 videos/sorted 2023-01-11 10:02:12 +01:00
bf31e8a4c9 video/preload=none 2023-01-11 09:43:07 +01:00
335e229aa5 css/draft 2023-01-10 23:33:54 +01:00
89fa362789 sections/home 2023-01-10 23:33:45 +01:00
7f2fbfcfb4 sections/sorted 2023-01-10 23:26:13 +01:00
9cf9eb8e7e build/nav 2023-01-10 23:06:09 +01:00
89e92e1160 css 2023-01-10 23:05:56 +01:00
8027fce02e encode 2023-01-10 23:05:36 +01:00
3 changed files with 252 additions and 0 deletions

113
build.py Executable file
View file

@ -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'''\
<div class="card">
<video controls="controls" preload="none">
<source src="{web}" />
</video>
<br />
<a href="{raw}">{name}</a>
</div>
'''
def a(href, text, active=False):
html = ['<a']
if active:
html.append(' class="active"')
html.append(f' href="{href}">{text}</a>')
return str().join(html)
def nav(sections, active):
html = ['<nav>']
for _, section in sorted(sections.items()):
id = section['id']
html.append(a(f"#{id}", section['label'], id == active))
html.append('</nav>')
return str().join(html)
def body(sections):
html = []
for _, section in sorted(sections.items()):
html.append(f'<section id="{section["id"]}">')
html.append(section['content'])
html.append('</section>')
return str().join(html)
def html(body):
return f'''\
<!DOCTYPE html><html><head>
<!----------------------------------------------------------------------------->
<meta charset="UTF-8" />
<link rel="stylesheet" href="index.css" />
<title>TrackMania vidz</title>
<!----------------------------------------------------------------------------->
</head></body>
<!----------------------------------------------------------------------------->
{body}
<!----------------------------------------------------------------------------->
</body></html>
'''
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([
'<div class="cards">', os.linesep.join(content), '</div>'])
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()

49
encode.py Executable file
View file

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

90
index.css Normal file
View file

@ -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;
}