Commit 9ecec3b1 authored by Michael Koscher's avatar Michael Koscher
Browse files

add Chat functionality and smaller improvments

parent aa1ba2ab
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
#!/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
# 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
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
<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()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment