Style player in seperate CSS file

This commit is contained in:
Alexandre Iooss 2020-10-11 10:54:10 +02:00
parent 8de28e4781
commit 064e35935d
No known key found for this signature in database
GPG Key ID: 6C79278F3FCDCC02
5 changed files with 148 additions and 127 deletions

84
web/static/css/player.css Normal file
View File

@ -0,0 +1,84 @@
/* Player */
.video-responsive {
position: relative;
padding-top: 56.25%; /* 16/9 */
}
.video-responsive video {
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
max-height: 90vh;
/* Black borders when video is not 16/9 */
background-color: #000;
}
/* Controls under the player */
.controls {
background: #0A1A28;
padding: 0.2rem 0.5rem;
color: rgb(187, 187, 187);
user-select: none;
}
.control-quality,
.control-srt-link,
.control-viewers,
.control-indicator,
.control-chat {
white-space: nowrap;
margin-left: 0.5rem;
}
/* Control icons */
.control-quality::before,
.control-srt-link::before,
.control-viewers::before {
content: "";
display: inline-block;
width: 16px;
height: 16px;
margin-right: 0.2rem;
vertical-align: middle;
}
.control-quality::before {
background: transparent url("data:image/svg+xml;utf8,<svg fill='rgb(187, 187, 187)' width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' d='M1.5 2A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13zm1 2a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 1 0V5h2.5a.5.5 0 0 0 0-1h-3zm11 8a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-1 0V11h-2.5a.5.5 0 0 0 0 1h3z'/></svg>") no-repeat;
}
.control-srt-link::before {
background: transparent url("data:image/svg+xml;utf8,<svg fill='rgb(187, 187, 187)' width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg'><path d='M1.5 13A1.5 1.5 0 0 0 3 14.5h8a1.5 1.5 0 0 0 1.5-1.5V9a.5.5 0 0 0-1 0v4a.5.5 0 0 1-.5.5H3a.5.5 0 0 1-.5-.5V5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 0 0-1H3A1.5 1.5 0 0 0 1.5 5v8zm7-11a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-1 0V2.5H9a.5.5 0 0 1-.5-.5z' /><path d='M14.354 1.646a.5.5 0 0 1 0 .708l-8 8a.5.5 0 0 1-.708-.708l8-8a.5.5 0 0 1 .708 0z'/></svg>") no-repeat;
}
.control-viewers::before {
background: transparent url("data:image/svg+xml;utf8,<svg fill='rgb(187, 187, 187)' width='16' height='16' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg'><path d='M10 11c-5.92 0-8 3-8 5v3h16v-3c0-2-2.08-5-8-5z'/><circle cx='10' cy='5.5' r='4.5'/></svg>") no-repeat;
}
.control-indicator {
vertical-align: middle;
}
/* Custom select */
.control-quality select {
border: none;
color: inherit;
appearance: none;
/* Custom caret */
background: transparent url("data:image/svg+xml;utf8,<svg fill='rgb(187, 187, 187)' width='10' height='5' viewBox='0 0 10 5' xmlns='http://www.w3.org/2000/svg'><path d='m0 0 5 5 5-5z'/></svg>") no-repeat right;
padding-right: 0.8rem;
}
/* Hide chat toggler on small screen */
.control-chat {
display: none;
}
@media(min-width:1000px){
.control-chat {
display: inline;
}
}

View File

@ -1,3 +1,5 @@
/* Commun style */
body, html { body, html {
height: 100%; height: 100%;
margin: 0; margin: 0;
@ -5,13 +7,12 @@ body, html {
body { body {
background-color: #3b4b5b; background-color: #3b4b5b;
font-family: "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; font-family: sans-serif;
font-size: 1rem; font-size: 1rem;
font-weight: 400; font-weight: 400;
line-height: 1.5; line-height: 1.5;
color: #bbb; color: #bbb;
text-align: justify; text-align: justify;
user-select: none;
} }
p { p {
@ -20,14 +21,10 @@ p {
} }
code { code {
font-size: 87.5%; font-family: monospace;
font-size: 10pt;
word-break: break-word; word-break: break-word;
user-select: text; user-select: all;
}
svg {
overflow: hidden;
vertical-align: middle;
} }
a { a {
@ -44,19 +41,6 @@ h1, h2, h3, h4 {
color: #ddd; color: #ddd;
} }
select {
border: none;
color: inherit;
appearance: none;
/* Custom caret */
background-color: transparent;
background-image: url("data:image/svg+xml;utf8,<svg fill='rgb(187, 187, 187)' height='24' viewBox='0 1 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/></svg>");
background-repeat: no-repeat;
background-position-x: 100%;
padding-right: 1.2rem;
}
.container { .container {
height: 100%; height: 100%;
width: 100%; width: 100%;
@ -76,24 +60,6 @@ select {
max-width: 1200px; max-width: 1200px;
} }
.video-responsive {
position: relative;
padding-top: 56.25%; /* 16/9 */
}
.video-responsive video {
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
max-height: 90vh;
/* Black borders when video is not 16/9 */
background-color: #000;
}
.col-chat { .col-chat {
position: relative; position: relative;
width: 100%; width: 100%;
@ -111,23 +77,10 @@ select {
border: 0; border: 0;
} }
.ml-1 {
margin-left: 0.5rem;
}
/* Hide chat toggler on small screen */
#sideWidgetToggle {
display: none;
}
/* On large screen, put chat on left */ /* On large screen, put chat on left */
@media(min-width:1000px){ @media(min-width:1000px){
.col-chat { .col-chat {
width: 33.33333%; width: 33.33333%;
flex: 0 0 33.33333%; flex: 0 0 33.33333%;
} }
#sideWidgetToggle {
display: inline;
}
} }

View File

@ -6,12 +6,13 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>{{if .Path}}{{if not .Cfg.OneStreamPerDomain}}{{.Path}} - {{end}}{{end}}{{.Cfg.Name}}</title> <title>{{if .Path}}{{if not .Cfg.OneStreamPerDomain}}{{.Path}} - {{end}}{{end}}{{.Cfg.Name}}</title>
<link rel="stylesheet" href="static/css/style.css"> <link rel="stylesheet" href="static/css/style.css">
<link rel="stylesheet" href="static/css/player.css">
<link rel="shortcut icon" href="{{.Cfg.Favicon}}"> <link rel="shortcut icon" href="{{.Cfg.Favicon}}">
</head> </head>
<body> <body>
{{if .Path}} {{if .Path}}
{{template "viewer" .}} {{template "player" .}}
{{else}} {{else}}
{{template "index" .}} {{template "index" .}}
{{end}} {{end}}

56
web/template/player.html Normal file
View File

@ -0,0 +1,56 @@
{{define "player"}}
<div class="container">
<div class="col-video">
<!-- Video -->
<div class="video-responsive">
<video id="viewer" poster="/static/img/no_stream.svg" muted controls autoplay></video>
</div>
<!-- Links and settings under video -->
<div class="controls">
<span class="control-quality">
<select id="quality">
<option value="">Source</option>
<option value="@720p">720p</option>
<option value="@480p">480p</option>
<option value="@240p">240p</option>
</select>
</span>
<code class="control-srt-link">srt://{{.Cfg.Hostname}}:{{.Cfg.SRTServerPort}}?streamid={{.Path}}</code>
<span class="control-viewers" id="connected-people">0</span>
<svg class="control-indicator" id="connectionIndicator" fill="#dc3545" width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<rect width="4" height="5" x="1" y="10" rx="1"/>
<rect width="4" height="9" x="6" y="6" rx="1"/>
<rect width="4" height="14" x="11" y="1" rx="1"/>
</svg>
{{if .WidgetURL}}<a class="control-chat" id="sideWidgetToggle" href="#" title="Cacher/Afficher le chat">»</a>{{end}}
</div>
</div>
{{if .WidgetURL}}
<!-- Chat -->
<div class="col-chat" id="sideWidget">
<iframe src="{{.WidgetURL}}"
title="Chat" sandbox="allow-scripts allow-forms allow-same-origin"></iframe>
</div>
{{end}}
</div>
{{if .WidgetURL}}<script src="/static/js/sideWidget.js"></script>{{end}}
<script src="/static/js/videoQuality.js"></script>
<script src="/static/js/viewer.js"></script>
<script src="/static/js/viewersCounter.js"></script>
<script>
const stunServers = [
{{range $id, $value := .Cfg.STUNServers}}
'{{$value}}',
{{end}}
]
startPeerConnection()
// Wait a bit before pulling viewers counter for the first time
setTimeout(() => {
refreshViewersCounter({{.Cfg.ViewersCounterRefreshPeriod}})
}, 1000)
</script>
{{end}}

View File

@ -1,73 +0,0 @@
{{define "viewer"}}
<div class="container">
<div class="col-video">
<!-- Video -->
<div class="video-responsive">
<video id="viewer" poster="/static/img/no_stream.svg" muted controls autoplay></video>
</div>
<!-- Links and settings under video -->
<p>
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-aspect-ratio-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M1.5 2A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13zm1 2a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 1 0V5h2.5a.5.5 0 0 0 0-1h-3zm11 8a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-1 0V11h-2.5a.5.5 0 0 0 0 1h3z"/>
</svg>
<select id="quality">
<option value="">Source</option>
<option value="@720p">720p</option>
<option value="@480p">480p</option>
<option value="@240p">240p</option>
</select>
<svg class="ml-1" width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-box-arrow-up-right" fill="#d7d7d7" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M1.5 13A1.5 1.5 0 0 0 3 14.5h8a1.5 1.5 0 0 0 1.5-1.5V9a.5.5 0 0 0-1 0v4a.5.5 0 0 1-.5.5H3a.5.5 0 0 1-.5-.5V5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 0 0-1H3A1.5 1.5 0 0 0 1.5 5v8zm7-11a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-1 0V2.5H9a.5.5 0 0 1-.5-.5z" />
<path fill-rule="evenodd"
d="M14.354 1.646a.5.5 0 0 1 0 .708l-8 8a.5.5 0 0 1-.708-.708l8-8a.5.5 0 0 1 .708 0z" />
</svg>
<code>srt://{{.Cfg.Hostname}}:{{.Cfg.SRTServerPort}}?streamid={{.Path}}</code>
<svg class="ml-1" width="1em" height="1em" viewBox="0 0 20 20" fill="#d7d7d7" xmlns="http://www.w3.org/2000/svg">
<path d="M10 11c-5.92 0-8 3-8 5v3h16v-3c0-2-2.08-5-8-5z"/>
<circle cx="10" cy="5.5" r="4.5"/>
</svg>
<span id="connected-people">0</span>
<svg id="connectionIndicator" class="ml-1" width="1em" height="1em" viewBox="0 0 16 16" fill="#dc3545" xmlns="http://www.w3.org/2000/svg">
<rect width="4" height="5" x="1" y="10" rx="1"/>
<rect width="4" height="9" x="6" y="6" rx="1"/>
<rect width="4" height="14" x="11" y="1" rx="1"/>
</svg>
{{if .WidgetURL}}
<a href="#" id="sideWidgetToggle" class="ml-1" title="Cacher/Afficher le chat">»</a>
{{end}}
</p>
</div>
{{if .WidgetURL}}
<!-- Chat -->
<div class="col-chat" id="sideWidget">
<iframe src="{{.WidgetURL}}"
title="Chat" sandbox="allow-scripts allow-forms allow-same-origin"></iframe>
</div>
{{end}}
</div>
{{if .WidgetURL}}<script src="/static/js/sideWidget.js"></script>{{end}}
<script src="/static/js/videoQuality.js"></script>
<script src="/static/js/viewer.js"></script>
<script src="/static/js/viewersCounter.js"></script>
<script>
const stunServers = [
{{range $id, $value := .Cfg.STUNServers}}
'{{$value}}',
{{end}}
]
startPeerConnection()
// Wait a bit before pulling viewers counter for the first time
setTimeout(() => {
refreshViewersCounter({{.Cfg.ViewersCounterRefreshPeriod}})
}, 1000)
</script>
{{end}}