mirror of
				https://gitlab.crans.org/nounous/ghostream.git
				synced 2025-11-04 15:42:26 +01:00 
			
		
		
		
	Style player in seperate CSS file
This commit is contained in:
		
							
								
								
									
										84
									
								
								web/static/css/player.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								web/static/css/player.css
									
									
									
									
									
										Normal 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;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
/* Commun style */
 | 
			
		||||
 | 
			
		||||
body, html {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
@@ -5,13 +7,12 @@ body, html {
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
  background-color: #3b4b5b;
 | 
			
		||||
  font-family: "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
 | 
			
		||||
  font-family: sans-serif;
 | 
			
		||||
  font-size: 1rem;
 | 
			
		||||
  font-weight: 400;
 | 
			
		||||
  line-height: 1.5;
 | 
			
		||||
  color: #bbb;
 | 
			
		||||
  text-align: justify;
 | 
			
		||||
  user-select: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
p {
 | 
			
		||||
@@ -20,14 +21,10 @@ p {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
code {
 | 
			
		||||
  font-size: 87.5%;
 | 
			
		||||
  font-family: monospace;
 | 
			
		||||
  font-size: 10pt;
 | 
			
		||||
  word-break: break-word;
 | 
			
		||||
  user-select: text;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
svg {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  vertical-align: middle;
 | 
			
		||||
  user-select: all;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a {
 | 
			
		||||
@@ -44,19 +41,6 @@ h1, h2, h3, h4 {
 | 
			
		||||
  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 {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
@@ -76,24 +60,6 @@ select {
 | 
			
		||||
  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 {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
@@ -111,23 +77,10 @@ select {
 | 
			
		||||
  border: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ml-1 {
 | 
			
		||||
  margin-left: 0.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Hide chat toggler on small screen */
 | 
			
		||||
#sideWidgetToggle {
 | 
			
		||||
  display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* On large screen, put chat on left */
 | 
			
		||||
@media(min-width:1000px){
 | 
			
		||||
  .col-chat {
 | 
			
		||||
    width: 33.33333%;
 | 
			
		||||
    flex: 0 0 33.33333%;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  #sideWidgetToggle {
 | 
			
		||||
    display: inline;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,12 +6,13 @@
 | 
			
		||||
  <meta charset="UTF-8">
 | 
			
		||||
  <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/player.css">
 | 
			
		||||
  <link rel="shortcut icon" href="{{.Cfg.Favicon}}">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
  {{if .Path}}
 | 
			
		||||
  {{template "viewer" .}}
 | 
			
		||||
  {{template "player" .}}
 | 
			
		||||
  {{else}}
 | 
			
		||||
  {{template "index" .}}
 | 
			
		||||
  {{end}}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										56
									
								
								web/template/player.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								web/template/player.html
									
									
									
									
									
										Normal 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}}
 | 
			
		||||
@@ -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}}
 | 
			
		||||
		Reference in New Issue
	
	Block a user