Skip to content

Commit

Permalink
Schildbrau 20 (#886)
Browse files Browse the repository at this point in the history
* Update devapp1.yml

New Release

* Bump async from 2.6.3 to 2.6.4 in /ui/dashboard (#887)

Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](caolan/async@v2.6.3...v2.6.4)

---
updated-dependencies:
- dependency-name: async
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Issue 738 Stream replays (#888)

* fix square frame/no frame video stream

* stream catch up techniques

* type safety

* Issue 889 Video issue (#891)

* modernize foyer

* fix static video dragging issue

* handle video load studio

* on loaded metadata

* Issue 882 System config interface (#893)

* reorder sidebar & typo

* email subject prefix saveable

* load email subject prefix from db

* config value instead of object

* defualt rehearsal status (#896)

* reload config after saving (#895)

* Issue 873 Stage visibility on Foyer (#894)

* stage visibility option

* update foyer display rule

* toggle and explaination (#899)

* move button from green banner (#902)

* fix broken stream url when broadcasting using obs (#905)

* remove button hide (#904)

* studio footer (#903)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Hồng Phát <hongphat.js@gmail.com>
  • Loading branch information
3 people authored Apr 29, 2022
1 parent 8a15430 commit 00b8ef5
Show file tree
Hide file tree
Showing 30 changed files with 598 additions and 487 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/devapp1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name: DEVAPP1 CI
on:
# Triggers the workflow on push or approved pull request on R1-2021 branch
push:
branches: [ Rheineck-19 ]
branches: [ Schildbrau-20 ]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
Expand All @@ -32,7 +32,7 @@ jobs:
script: |
cd /home/upstage/upstage/ui/dashboard/
git fetch
git checkout Rheineck-19
git checkout Schildbrau-20
git pull
yarn
yarn build:dev
Expand Down
4 changes: 4 additions & 0 deletions config/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

TERMS_OF_SERVICE = 'TERMS_OF_SERVICE'
MANUAL = 'MANUAL'
EMAIL_SUBJECT_PREFIX = 'EMAIL_SUBJECT_PREFIX'


class NginxConfig(graphene.ObjectType):
Expand Down Expand Up @@ -44,13 +45,16 @@ def get_config(name):
class SystemConfig(graphene.ObjectType):
termsOfService = graphene.String()
manual = graphene.String()
esp = graphene.String()

def resolve_termsOfService(self, info):
return get_config(TERMS_OF_SERVICE)

def resolve_manual(self, info):
return get_config(MANUAL)

def resolve_esp(self, info):
return get_config(EMAIL_SUBJECT_PREFIX)

class FoyerConfig(graphene.ObjectType):
title = graphene.String()
Expand Down
6 changes: 4 additions & 2 deletions mail/mail_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
import sys
import os
import re
from config.models import Config
from config.project_globals import DBSession

from config.settings import (EMAIL_HOST, EMAIL_PORT,
EMAIL_HOST_USER, EMAIL_HOST_PASSWORD, EMAIL_HOST_DISPLAY_NAME,
ADMIN_EMAIL, ENV_TYPE)

def send_sync(to, subject, content):

subject_prefix = DBSession.query(Config).filter(Config.name == 'EMAIL_SUBJECT_PREFIX').first().value
msg = MIMEText(content, "html")
msg["Subject"] = f'{ENV_TYPE}: {subject}'
msg["Subject"] = f'{subject_prefix}: {subject}'
# some SMTP servers will do this automatically, not all
msg["From"] = f'{EMAIL_HOST_DISPLAY_NAME} <{EMAIL_HOST_USER}>'
msg["To"] = to
Expand Down
7 changes: 5 additions & 2 deletions stage/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class StageAttribute:
name = graphene.String(description="Stage Name")
description = graphene.String(description="Stage Description")
file_location = graphene.String(description="Unique File Location")
status = graphene.String(description="Live/Upcoming/Rehearsal")
status = graphene.String(description="Live/Rehearsal")
visibility = graphene.Boolean(description="Show or hide the stage on the Foyer")
cover = graphene.String(description="Cover image url")
media = graphene.String(description="Media attached to stage")
config = graphene.String(description="Stage configurations")
Expand Down Expand Up @@ -232,7 +233,9 @@ def mutate(self, info, input):
continue
if hasattr(stage, key):
setattr(stage, key, value)
elif value:
elif value != None:
if not value:
value = ''
attribute = stage.attributes.filter(
StageAttributeModel.name == key
).first()
Expand Down
2 changes: 1 addition & 1 deletion ui/dashboard/.env.localhost
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
VUE_APP_API_ENDPOINT=http://127.0.0.1:5000/api/
VUE_APP_GRAPHQL_ENDPOINT=http://127.0.0.1:5000/api/
VUE_APP_STATIC_ASSETS_ENDPOINT=https://dev-app1.upstage.live/static/assets/
VUE_APP_STATIC_ASSETS_ENDPOINT=https://upstage.live/static/assets/
VUE_APP_MQTT_NAMESPACE=dev
VUE_APP_JITSI_ENDPOINT=https://streaming1.upstage.live/
3 changes: 2 additions & 1 deletion ui/dashboard/jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"@/*": [
"./src/*"
]
}
},
"jsx": "preserve"
},
"exclude": [
"node_modules",
Expand Down
4 changes: 2 additions & 2 deletions ui/dashboard/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "dashboard",
"version": "1.19.0",
"versionAlias": "Rheineck-19",
"version": "1.20.0",
"versionAlias": "Schildbrau-20",
"license": "GPL-3.0",
"private": true,
"scripts": {
Expand Down
Binary file added ui/dashboard/public/img/foyer-background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 13 additions & 2 deletions ui/dashboard/src/components/RTMPStream.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,27 @@
</template>

<script>
import { computed, ref } from "@vue/runtime-core";
import { computed, ref, onMounted } from "@vue/runtime-core";
import { getSubsribeLink } from "@/utils/streaming";
import { useFlv } from "./objects/Streamer/composable";
export default {
props: ["src"],
setup: (props) => {
emits: ['scan'],
setup: (props, { emit }) => {
const video = ref();
const fullUrl = computed(() => getSubsribeLink(props.src));
const { playable } = useFlv(video, fullUrl);
onMounted(() => {
video.value.addEventListener("loadedmetadata", () => {
emit('scan', {
width: video.value.videoWidth,
height: video.value.videoHeight,
duration: video.value.duration,
video: video.value
});
});
})
return { video, playable };
},
};
Expand Down
26 changes: 25 additions & 1 deletion ui/dashboard/src/components/objects/Streamer/composable.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { onMounted, ref, watch } from "vue";
import { onBeforeUnmount, onMounted, ref, watch } from "vue";
import { cropImageFromCanvas } from "@/utils/canvas";
import flvjs from "flv.js";

Expand Down Expand Up @@ -86,11 +86,35 @@ export const useFlv = (video, src) => {
});
flvPlayer.attachMediaElement(video.value);
flvPlayer.load();
flvPlayer.on(flvjs.Events.ERROR, () => {
playable.value = false
});
video.value.addEventListener('ended', () => {
playable.value = false
}, { once: true });
}
};

onMounted(initPlayer);
watch(src, initPlayer);

return { playable }
}

export const useCatchup = (video) => {
const onProgress = () => {
if (video.value.buffered.length) {
var end = video.value.buffered.end(0);
var delta = end - video.value.currentTime;
if (delta > 3) {
video.value.currentTime = (end - 0.5)
}
}
}
onMounted(() => {
video.value.addEventListener('progress', onProgress);
})
onBeforeUnmount(() => {
video.value.removeEventListener('progress', onProgress);
})
}
34 changes: 14 additions & 20 deletions ui/dashboard/src/components/objects/Streamer/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,11 @@

<template #render>
<Loading v-if="loading" height="100%" />
<video
v-bind:id="'video' + stream.id"
v-show="!loading"
ref="video"
:src="object.url"
:muted="localMuted"
preload="auto"
disablepictureinpicture
@loadeddata="loadeddata"
@ended="stream.isPlaying = false"
:style="{
<video v-bind:id="'video' + stream.id" v-show="!loading" ref="video" :src="object.url" :muted="localMuted"
preload="auto" disablepictureinpicture @loadeddata="loadeddata" @ended="stream.isPlaying = false" :style="{
'border-radius': stream.shape === 'circle' ? '100%' : 0,
}"
></video>
<button
v-if="isPlayer"
class="button is-small mute-icon clickable"
@mousedown="toggleMuted"
>
}"></video>
<button v-if="isPlayer" class="button is-small mute-icon clickable" @mousedown="toggleMuted">
<i v-if="localMuted" class="fas fa-volume-mute has-text-danger"></i>
<i v-else class="fas fa-volume-up has-text-primary"></i>
</button>
Expand All @@ -38,7 +24,7 @@
import { computed, reactive, ref, watch } from "vue";
import Object from "../Object.vue";
import { useStore } from "vuex";
import { useFlv } from "./composable";
import { useFlv, useCatchup } from "./composable";
import { getSubsribeLink } from "@/utils/streaming";
import Loading from "@/components/Loading.vue";
import MenuContent from '../Avatar/ContextMenu'
Expand Down Expand Up @@ -78,7 +64,15 @@ export default {
if (props.object.isRTMP) {
const fullUrl = computed(() => getSubsribeLink(props.object.url));
useFlv(video, fullUrl);
useCatchup(video);
const { playable } = useFlv(video, fullUrl);
watch(playable, value => {
console.log("playable", value);
if (!value) {
store.dispatch("stage/deleteObject", props.object);
}
})
}
const clip = (shape) => {
Expand Down
70 changes: 70 additions & 0 deletions ui/dashboard/src/components/stage/Entry.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<template>
<div class="p-4">
<router-link :to="`/${stage.fileLocation}`" class="stage">
<img class="cover" :src="coverImage(stage.cover)" lazy>
<PlayerAudienceCounter :stage-url="stage.fileLocation" class="counter" />
<span class="name">{{ stage.name }}</span>
</router-link>
</div>
</template>

<script setup>
import { defineProps } from 'vue';
import config from "@/../vue.config";
import PlayerAudienceCounter from "@/components/stage/PlayerAudienceCounter";
import { absolutePath } from '@/utils/common';
const props = defineProps({
stage: {
type: Object,
required: true,
},
fallbackCover: {
type: String,
},
});
console.log(props.fallbackCover, `${config.publicPath}img/${props.fallbackCover}`);
const coverImage = (src) => src ? absolutePath(src) : `${config.publicPath}img/${props.fallbackCover}`;
</script>

<style lang="scss" scoped>
@import "@/styles/bulma";
@import "@/styles/mixins";
.stage {
@include textShadow;
position: relative;
font-weight: bold;
font-size: 25px;
border: 1px solid $black;
border-top: 10px solid $primary;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
box-shadow: 10px 5px 0 0 $black;
color: white;
border-radius: 12px;
overflow: hidden;
.cover {
width: 100%;
height: 100%;
min-height: 200px;
background-size: cover;
}
.name {
position: absolute;
z-index: 10;
padding: 2rem;
}
.counter {
position: absolute;
right: 10px;
top: 10px;
width: auto !important;
}
}
</style>
32 changes: 26 additions & 6 deletions ui/dashboard/src/components/stage/Toolbox/tools/Streams/index.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<template>
<div v-for="stream in streams" :key="stream">
<Skeleton :data="stream">
<div v-for="stream in streams" :key="stream" :class="{ 'has-background-warning': !stream.ready && stream.alive }">
<Skeleton :data="stream" :nodrop="stream.isRTMP && !stream.ready">
<template v-if="stream.isRTMP">
<div class="centered">
<RTMPStream v-if="stream.alive" :src="stream.url"></RTMPStream>
<RTMPStream v-if="stream.alive" :src="stream.url" @scan="scanVideo($event, stream)"></RTMPStream>
<QRCodePopup v-else :stream="stream" />
</div>
</template>
Expand Down Expand Up @@ -60,8 +60,10 @@ export default {
const index = res.findIndex((s) => s.url === stream.url);
if (index >= 0) {
res[index].alive = true;
res[index].w = stream.w
res[index].h = stream.h
if (stream.w > 0 && stream.h > 0) {
res[index].w = stream.w
res[index].h = stream.h
}
} else {
if (autoDetect.value) {
res.push(stream);
Expand All @@ -72,20 +74,38 @@ export default {
return res;
});
return { streams, loading, fetchRunningStreams, autoDetect };
const scanVideo = ({ width, height }, stream) => {
console.log(stream, width, height)
if (!stream.ready) {
Object.assign(stream, {
w: 100 * width / height,
h: 100,
ready: true
})
}
}
return { streams, loading, fetchRunningStreams, autoDetect, scanVideo };
},
};
</script>
<style lang="scss" scoped>
@import "@/styles/mixins.scss";
.fas.fa-plus {
@include gradientText(#30ac45, #6fb1fc);
}
video {
height: 100%;
}
.centered {
margin: auto;
}
.pending-stream {
cursor: not-allowed;
}
</style>
Loading

0 comments on commit 00b8ef5

Please sign in to comment.