Skip to content
Snippets Groups Projects
Commit 9ecec3b1 authored by Michael Koscher's avatar Michael Koscher
Browse files

add Chat functionality and smaller improvments

parent aa1ba2ab
No related branches found
No related tags found
No related merge requests found
.DS_Store 0 → 100644
File added
.env
*.yml
*.code-workspace
*.iml
\ No newline at end of file
......@@ -32,8 +32,13 @@ RUN apt-get update && \
ENV BBB_AS_MODERATOR false
ENV BBB_USER_NAME Live
ENV BBB_CHAT_NAME Chat
ENV BBB_ENABLE_CHAT false
ENV BBB_REDIS_HOST redis
ENV BBB_REDIS_CHANNEL chat
COPY stream.py ./
COPY chat.py ./
COPY startStream.sh ./
COPY docker-entrypoint.sh ./
......
......@@ -20,15 +20,20 @@ You need to set some environment variables to run the container.
#### Optional
* BBB_AS_MODERATOR - if set to "true" the meeting will be joined as moderator
* BBB_USER_NAME - the Username to join the meeting. (Default: Live)
* BBB_USER_NAME - the username to join the meeting. (Default: Live)
### Chat options
* BBB_ENABLE_CHAT - Enable Chat
* BBB_REDIS_HOST - Set REDIS host (Default: redis)
* BBB_REDIS_CHANNEL - Set REDIS channel (Default: chat)
* BBB_CHAT_NAME - the username to join the meeting for chatting. (Default: Chat)
### Starting liveStreaming
* wget -O docker-compose.yml https://github.com/aau-zid/BigBlueButton-liveStreaming/raw/master/docker-compose.yml.example
* (change configuration)
* docker-compose up -d
* docker-compose down
* docker-compose down
## Known Limitations
* You must extract and provide the meetingID, which is not visible within the room.
* Some unnecessary html elements are not hidden yet.
* ffmpeg settings to be improved
chat.py 0 → 100644
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, argparse, time, logging, os, redis
from bigbluebutton_api_python import BigBlueButton
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
browser = None
selelnium_timeout = 30
connect_timeout = 5
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
parser = argparse.ArgumentParser()
parser.add_argument("-s","--server", help="Big Blue Button Server URL")
parser.add_argument("-p","--secret", help="Big Blue Button Secret")
parser.add_argument("-i","--id", help="Big Blue Button Meeting ID")
parser.add_argument("-m","--moderator", help="Join the meeting as moderator",action="store_true")
parser.add_argument("-u","--user", help="Name to join the meeting",default="Live")
parser.add_argument("-r","--redis", help="Redis hostname",default="redis")
parser.add_argument("-c","--channel", help="Redis channel",default="chat")
args = parser.parse_args()
bbb = BigBlueButton(args.server,args.secret)
def set_up():
global browser
options = Options()
options.add_argument('--disable-infobars')
options.add_argument('--no-sandbox')
options.add_argument('--kiosk')
options.add_argument('--window-size=1920,1080')
options.add_argument('--window-position=0,0')
options.add_experimental_option("excludeSwitches", ['enable-automation'])
options.add_argument('--incognito')
options.add_argument('--shm-size=1gb')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--start-fullscreen')
logging.info('Starting browser to chat!!')
browser = webdriver.Chrome(executable_path='./chromedriver',options=options)
def bbb_browser():
global browser
logging.info('Open BBB for chat!!')
browser.get(get_join_url())
element = EC.presence_of_element_located((By.CSS_SELECTOR, '[aria-label="Listen only"]'))
WebDriverWait(browser, selelnium_timeout).until(element)
browser.find_elements_by_css_selector('[aria-label="Listen only"]')[0].click()
element = EC.invisibility_of_element((By.CSS_SELECTOR, '.ReactModal__Overlay'))
WebDriverWait(browser, selelnium_timeout).until(element)
redis_r = redis.Redis(host=args.redis,charset="utf-8", decode_responses=True)
redis_s = redis_r.pubsub()
redis_s.psubscribe(**{args.channel:chat_handler})
thread = redis_s.run_in_thread(sleep_time=0.001)
def chat_handler(message):
global browser
browser.find_element_by_id('message-input').send_keys(message['data'])
browser.find_elements_by_css_selector('[aria-label="Send message"]')[0].click()
logging.info(message['data'])
def get_join_url():
minfo = bbb.get_meeting_info(args.id)
if args.moderator:
pwd = minfo.get_meetinginfo().get_moderatorpw()
else:
pwd = minfo.get_meetinginfo().get_attendeepw()
return bbb.get_join_meeting_url(args.user,args.id,pwd)
def chat():
while True:
time.sleep(60)
while bbb.is_meeting_running(args.id).is_meeting_running() != True:
time.sleep(connect_timeout)
set_up()
bbb_browser()
chat()
browser.quit()
\ No newline at end of file
File added
# BigBlueButton Server url:
BBB_URL=https://your_BigBlueButton_server/bigbluebutton/api
# BigBlueButton secret:
BBB_SECRET=your_secret
# BigBlueButton meetingID:
BBB_MEETING_ID=your_meetingID
# Media server url:
BBB_STREAM_URL=rtmp://media_server_url/stream/stream_key
# Enable chat functionality
BBB_ENABLE_CHAT=true
# Set REDIS host (default: 'redis')
BBB_REDIS_HOST=redis
# Set REDIS channel to subscribe (default: 'chat')
BBB_REDIS_CHANNEL=chat
# Username for the chat (default: 'Chat')
BBB_CHAT_NAME=Chat
\ No newline at end of file
File moved
version: "3.3"
services:
redis:
image: redis
networks:
- app-tier
bbb-streamer:
image: aauzid/bigbluebutton-livestreaming
environment:
# BigBlueButton Server url:
- BBB_URL=https://your_BigBlueButton_server/bigbluebutton/api
# BigBlueButton secret:
- BBB_SECRET=your_secret
# BigBlueButton meetingID:
- BBB_MEETING_ID=your_meetingID
# Media server url:
- BBB_STREAM_URL=rtmp://media_server_url/stream/stream_key
# Enable chat functionality
-BBB_ENABLE_CHAT=true
# Set REDIS host (default: 'redis')
-BBB_REDIS_HOST=redis
# Set REDIS channel to subscribe (default: 'chat')
-BBB_REDIS_CHANNEL=chat
# Username for the chat (default: 'Chat')
-BBB_CHAT_NAME=Chat
networks:
- app-tier
networks:
app-tier:
driver: bridge
\ No newline at end of file
File moved
<head>
<link href="https://vjs.zencdn.net/7.6.5/video-js.css" rel="stylesheet">
<script
src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"></script>
<!-- If you'd like to support IE8 (for Video.js versions prior to v7) -->
</head>
<body>
<h1>Live Stream</h1>
<div style="float:left; width:49%">
<video id='my-video-live' class="video-js vjs-default-skin" width='760' height='400'>
<source src="LIVE_STREAM_URL">
<p class='vjs-no-js'>
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href='http://videojs.com/html5-video-support/' target='_blank'>supports HTML5 video</a>
</p>
</video>
</div>
<div id="container" style=" float:right; width:49%">
<form method="post" action="" id="contactform">
<div class="form-group">
<h2 >Send Question</h2>
<textarea name="message" rows="15" cols="60" class="form-control" id="message"></textarea>
</div>
<button type="submit" class="btn btn-primary send-message">Submit</button>
</form>
</div>
<script src='https://vjs.zencdn.net/7.6.6/video.js'></script>
<script type="application/javascript">
$(document).ready(function () {
$('.send-message').click(function (e) {
e.preventDefault();
var message = $('#message').val();
$.ajax
({
type: "POST",
url: "sendChatMessage.php",
data: { "message": message },
success: function (data) {
$('#contactform')[0].reset();
}
});
});
});
</script>
</body>
\ No newline at end of file
<?php
if(!empty($_POST)) {
$message = $_POST['message'];
$redis = new Redis();
$redis->pconnect('REDIS_HOST'); // REDIS_HOST hast to be the same as in BBB_REDIS_HOST
$redis->publish('REDIS_CHANNEL', $message); // REDIS_CHANNEL hast to be the same as in BBB_REDIS_CHANNEL
echo "Message published\n";
\ No newline at end of file
......@@ -4,6 +4,12 @@ JOIN_AS_MODERATOR="";
if [ "${BBB_AS_MODERATOR}" = "true" ]
then
JOIN_AS_MODERATOR="-m";
fi
fi
xvfb-run -n 122 --server-args="-screen 0 1280x720x24" python3 stream.py -s ${BBB_URL} -p ${BBB_SECRET} -i ${BBB_MEETING_ID} -t ${BBB_STREAM_URL} -u ${BBB_USER_NAME} $JOIN_AS_MODERATOR;
if [ "${BBB_ENABLE_CHAT}" = "true" ]
then
xvfb-run -n 133 --server-args="-screen 0 1920x1080x24" python3 chat.py -s ${BBB_URL} -p ${BBB_SECRET} -i ${BBB_MEETING_ID} -r ${BBB_REDIS_HOST} -u ${BBB_CHAT_NAME} -c ${BBB_REDIS_CHANNEL} $JOIN_AS_MODERATOR &
sleep 10
fi
xvfb-run -n 122 --server-args="-screen 0 1920x1080x24" python3 stream.py -s ${BBB_URL} -p ${BBB_SECRET} -i ${BBB_MEETING_ID} -t ${BBB_STREAM_URL} -u ${BBB_USER_NAME} $JOIN_AS_MODERATOR;
......@@ -13,7 +13,8 @@ from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
browser = None
timeout = 5
selelnium_timeout = 30
connect_timeout = 5
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
......@@ -32,21 +33,14 @@ def set_up():
global browser
options = Options()
#options.set_headless(headless=True)
#options.add_argument("--headless")
#options.add_argument('--enable-logging=stderr')
#options.add_argument('--disable-gpu')
#options.add_argument('--enable-usermedia-screen-capturing')
#options.add_argument('--allow-http-screen-capture')
#options.add_argument('--auto-select-desktop-capture-source=bbbrecorder')
options.add_argument('--disable-infobars')
options.add_argument('--no-sandbox')
options.add_argument('--kiosk')
options.add_argument('--window-size=1280,720')
options.add_argument('--window-size=1920,1080')
options.add_argument('--window-position=0,0')
options.add_experimental_option("excludeSwitches", ['enable-automation']);
#options.add_argument('--shm-size=1gb')
#options.add_argument('--disable-dev-shm-usage')
options.add_argument('--shm-size=1gb')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--start-fullscreen')
logging.info('Starting browser!!')
......@@ -59,13 +53,15 @@ def bbb_browser():
logging.info('Open BBB and hide elements!!')
browser.get(get_join_url())
element = EC.presence_of_element_located((By.CSS_SELECTOR, '[aria-label="Listen only"]'))
WebDriverWait(browser, timeout).until(element)
WebDriverWait(browser, selelnium_timeout).until(element)
browser.find_elements_by_css_selector('[aria-label="Listen only"]')[0].click()
element = EC.invisibility_of_element((By.CSS_SELECTOR, '.ReactModal__Overlay'))
WebDriverWait(browser, timeout).until(element)
WebDriverWait(browser, selelnium_timeout).until(element)
browser.find_elements_by_id('chat-toggle-button')[0].click()
browser.find_elements_by_css_selector('button[aria-label="Users and messages toggle"]')[0].click()
browser.execute_script("document.querySelector('[aria-label=\"Users and messages toggle\"]').style.display='none';")
browser.execute_script("document.querySelector('[aria-label=\"Options\"]').style.display='none';")
def get_join_url():
minfo = bbb.get_meeting_info(args.id)
......@@ -80,16 +76,16 @@ def watch():
time.sleep(60)
def stream():
logging.info('Starting Stream with cmd: ffmpeg -fflags +igndts -f x11grab -s 1280x720 -r 24 -draw_mouse 0 -i :%d -f alsa -i pulse -ac 2 -preset ultrafaset -crf 0 -pix_fmt yuv420p -s 1280x720 -c:a aac -b:a 160k -ar 44100 -threads 0 -f flv "%s"' % (122, args.target))
ffmpeg_stream = 'ffmpeg -fflags +igndts -f x11grab -s 1280x720 -r 24 -draw_mouse 0 -i :%d -f alsa -i pulse -ac 2 -preset ultrafaset -pix_fmt yuv420p -s 1280x720 -c:a aac -b:a 160k -ar 44100 -threads 0 -f flv "%s"' % (122, args.target)
logging.info('Starting Stream with cmd: ffmpeg -fflags +igndts -f x11grab -s 1920x1080 -r 24 -draw_mouse 0 -i :%d -f alsa -i pulse -ac 2 -preset ultrafaset -crf 0 -pix_fmt yuv420p -s 1920x1080 -c:a aac -b:a 160k -ar 44100 -threads 0 -f flv "%s"' % (122, args.target))
ffmpeg_stream = 'ffmpeg -fflags +igndts -f x11grab -s 1920x1080 -r 24 -draw_mouse 0 -i :%d -f alsa -i pulse -ac 2 -preset ultrafaset -pix_fmt yuv420p -s 1920x1080 -c:a aac -b:a 160k -ar 44100 -threads 0 -f flv "%s"' % (122, args.target)
ffmpeg_args = shlex.split(ffmpeg_stream)
p = subprocess.Popen(ffmpeg_args)
while bbb.is_meeting_running(args.id).is_meeting_running() != True:
logging.info("Meeting isn't running. We will try again in %d seconds!" % timeout)
time.sleep(timeout)
logging.info("Meeting isn't running. We will try again in %d seconds!" % connect_timeout)
time.sleep(connect_timeout)
set_up()
bbb_browser()
stream()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment