@aaronkvanmeerten @nightstryke
thanks for your help.
i have updated the config to below:
// The hosts of the XMPP servers to connect to as part of
// this environment
"xmpp_server_hosts": [
"onestar.cloud"
],
// The xmpp domain we'll connect to on the XMPP server
"xmpp_domain": "onestar.cloud",
// Jibri will login to the xmpp server as a privileged user
"control_login": {
// The domain to use for logging in
"domain": "auth.onestar.cloud",
// The credentials for logging in
"username": "jibri",
"password": "jibriauthpass"
},
// Using the control_login information above, Jibri will join
// a control muc as a means of announcing its availability
// to provide services for a given environment
"control_muc": {
"domain": "internal.auth.onestar.cloud",
"room_name": "2017",
"nickname": "jibri-nickname"
},
// All participants in a call join a muc so they can exchange
// information. Jibri can be instructed to join a special muc
// with credentials to give it special abilities (e.g. not being
// displayed to other users like a normal participant)
"call_login": {
"domain": "recorder.onestar.cloud",
"username": "recorder",
"password": "jibrirecorderpass"
},
// When jibri gets a request to start a service for a room, the room
// jid will look like:
// roomName@optional.prefixes.subdomain.xmpp_domain
// We'll build the url for the call by transforming that into:
// https://xmpp_domain/subdomain/roomName
// So if there are any prefixes in the jid (like jitsi meet, which
// has its participants join a muc at conference.xmpp_domain) then
// list that prefix here so it can be stripped out to generate
// the call url correctly
"room_jid_domain_string_to_strip_from_start": "conference.",
// The amount of time, in minutes, a service is allowed to continue.
// Once a service has been running for this long, it will be
// stopped (cleanly). A value of 0 means an indefinite amount
// of time is allowed
"usage_timeout": "0"
}
]
}
but it failed again if i started it with service command.
sudo systemctl status jibri.service
● jibri.service — Jibri Process
Loaded: loaded (/etc/systemd/system/jibri.service; disabled; vendor preset: enabled)
Active: inactive (dead)
May 25 13:44:18 ubuntu graceful_shutdown.sh[13762]: % Total % Received % Xferd Average Speed Time Time Time Current
May 25 13:44:18 ubuntu graceful_shutdown.sh[13762]: Dload Upload Total Spent Left Speed
May 25 13:44:18 ubuntu graceful_shutdown.sh[13762]: [149B blob data]
May 25 13:44:18 ubuntu systemd[1]: jibri.service: Control process exited, code=exited status=7
May 25 13:44:18 ubuntu systemd[1]: jibri.service: Unit entered failed state.
May 25 13:44:18 ubuntu systemd[1]: jibri.service: Failed with result ‘exit-code’.
May 25 13:44:18 ubuntu systemd[1]: jibri.service: Service hold-off time over, scheduling restart.
May 25 13:44:18 ubuntu systemd[1]: Stopped Jibri Process.
May 25 13:44:18 ubuntu systemd[1]: jibri.service: Start request repeated too quickly.
May 25 13:44:18 ubuntu systemd[1]: Failed to start Jibri Process.
ubuntu@ubuntu:/etc/jitsi/jibri$
i have tried to start it with scripts, there are logs below:
ubuntu@ubuntu:/etc/jitsi/jibri$ sudo /opt/jitsi/jibri/launch.sh
2018-05-25 13:45:32.982 INFO: [1] org.jitsi.jibri.Main.main() Using config file /etc/jitsi/jibri/config.json
2018-05-25 13:45:33.561 INFO: [1] org.jitsi.jibri.Main.loadConfig() Parsed config:
JibriConfig(recordingDirectory=/tmp/recordings, finalizeRecordingScriptPath=/path/to/finalize_recording.sh, xmppEnvironments=[XmppEnvironmentConfig(name=prod, xmppServerHosts=[onestar.cloud], xmppDomain=onestar.cloud, controlLogin=XmppCredentials(domain=auth.onestar.cloud, username=jibri, password=jibriauthpass), controlMuc=XmppMuc(domain=internal.auth.onestar.cloud, roomName=2017, nickname=jibri-nickname), sipControlMuc=null, callLogin=XmppCredentials(domain=recorder.onestar.cloud, username=recorder, password=jibrirecorderpass), stripFromRoomDomain=conference., usageTimeoutMins=0, trustAllXmppCerts=true)])
2018-05-25 13:45:33.599:INFO::main: Logging initialized @861ms
2018-05-25 13:45:33.626:WARN:oejsh.ContextHandler:main: o.e.j.s.ServletContextHandler@1603cd68{/,null,null} contextPath ends with /*
2018-05-25 13:45:33.626:WARN:oejsh.ContextHandler:main: Empty contextPath
2018-05-25 13:45:33.629:INFO:oejs.Server:main: jetty-9.2.z-SNAPSHOT
2018-05-25 13:45:33.910 WARNING: [1] org.glassfish.jersey.internal.inject.Providers.checkProviderRuntime() A provider org.jitsi.jibri.api.http.internal.InternalHttpApi registered in SERVER runtime does not implement any provider interfaces applicable in the SERVER runtime. Due to constraint configuration problems the provider org.jitsi.jibri.api.http.internal.InternalHttpApi will be ignored.
2018-05-25 13:45:33.999:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@1603cd68{/,null,AVAILABLE}
2018-05-25 13:45:34.007:INFO:oejs.ServerConnector:main: Started ServerConnector@438bad7c{HTTP/1.1}{0.0.0.0:3333}
2018-05-25 13:45:34.008:INFO:oejs.Server:main: Started @1271ms
2018-05-25 13:45:34.101 INFO: [1] org.jitsi.jibri.api.xmpp.XmppApi.start() Connecting to xmpp environment on onestar.cloud with config XmppEnvironmentConfig(name=prod, xmppServerHosts=[onestar.cloud], xmppDomain=onestar.cloud, controlLogin=XmppCredentials(domain=auth.onestar.cloud, username=jibri, password=jibriauthpass), controlMuc=XmppMuc(domain=internal.auth.onestar.cloud, roomName=2017, nickname=jibri-nickname), sipControlMuc=null, callLogin=XmppCredentials(domain=recorder.onestar.cloud, username=recorder, password=jibrirecorderpass), stripFromRoomDomain=conference., usageTimeoutMins=0, trustAllXmppCerts=true)
2018-05-25 13:45:34.107 INFO: [1] org.jitsi.jibri.api.xmpp.XmppApi.start() The trustAllXmppCerts config is enabled for this domain, all XMPP server provided certificates will be accepted
2018-05-25 13:45:34.268 INFO: [1] class org.jitsi.xmpp.mucclient.MucClient.connected() Xmpp connection status [auth.onestar.cloud]: connected
2018-05-25 13:45:34.290 INFO: [1] class org.jitsi.xmpp.mucclient.MucClient.authenticated() Xmpp connection status [auth.onestar.cloud]: authenticated
2018-05-25 13:45:34.303 INFO: [1] org.jitsi.jibri.api.xmpp.XmppApi.invoke() Jibri reports its status is now idle, publishing presence to connection prod
2018-05-25 13:45:34.304:WARN:oejsh.ContextHandler:main: o.e.j.s.ServletContextHandler@53692008{/,null,null} contextPath ends with /*
2018-05-25 13:45:34.305:WARN:oejsh.ContextHandler:main: Empty contextPath
2018-05-25 13:45:34.305:INFO:oejs.Server:main: jetty-9.2.z-SNAPSHOT
2018-05-25 13:45:34.332 WARNING: [1] org.glassfish.jersey.internal.inject.Providers.checkProviderRuntime() A provider org.jitsi.jibri.api.http.HttpApi registered in SERVER runtime does not implement any provider interfaces applicable in the SERVER runtime. Due to constraint configuration problems the provider org.jitsi.jibri.api.http.HttpApi will be ignored.
2018-05-25 13:45:34.356:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@53692008{/,null,AVAILABLE}
2018-05-25 13:45:34.356:INFO:oejs.ServerConnector:main: Started ServerConnector@3496655e{HTTP/1.1}{0.0.0.0:2222}
2018-05-25 13:45:34.357:INFO:oejs.Server:main: Started @1620ms
2018-05-25 13:46:05.251:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@332060d5{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.468:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@6d7efcc0{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.577:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@5f7d1e9e{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.630:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@4925f28f{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.646:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@63b91f1f{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.685:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@51bafb01{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.765:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@4971f6fd{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.801:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@678697b0{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.819:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@558575ee{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.206:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@4735f6d2{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.207:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@1087f13a{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.211:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@2739945a{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.314:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@12e77853{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.317:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@22841524{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.347:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@21dd014f{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.435:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@74b0410a{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.485:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@38067548{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.503:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@5f893a9f{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.556:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@32b0877f{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.617:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@13ecd4b0{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.657:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@70a80e75{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.700:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@5a5b649d{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.746:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@4084ea6a{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.846:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@1bd8cf7e{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.849:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@7357aa65{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.896:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@42abea6b{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.938:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@52466233{r=0,c=false,a=IDLE,uri=-}
could you check it again ?is there any mistake over there ?
2020-04-18 19:06:12.543 SEVERE: [21] org.jitsi.xmpp.mucclient.MucClientManager.log() Failed to initialize and start a MucClient:
org.jivesoftware.smack.SmackException$ConnectionException: The following addresses failed: ‘osboxes.demoanuswadh.info:5222’ failed because: osboxes.demoanuswadh.info/77.525.75.82 exception: java.net.ConnectException: Connection refused (Connection refused)
В вашем журнале указано, что jibri подключается к osboxes.demoanuswadh.info (будет ли он разрешен для localhost или общедоступного IP-адреса?)
Если вы установили jitsi-meet и jibri на одном хосте, убедитесь, что osboxes.demoanuswadh.info должен быть разрешен как localhost.
Если вы установили на другой компьютер в одной подсети, osboxes.demoanuswadh.info должен быть преобразован в частный IP-адрес.
Если вы установили на другой компьютер в одной подсети, osboxes.demoanuswadh.info должен быть преобразован в общедоступный IP-адрес.
В последних двух случаях убедитесь, что ваша просодия прослушивает привязку порта 5222 к 0.0.0.0, также разрешите доступ к брандмауэру с помощью ufw (брандмауэр ubuntu)
This Issue tracker is only for reporting bugs and tracking code related issues.
Before posting, please make sure you check community.jitsi.org to see if the same or similar bugs have already been discussed. General questions, installation help, and feature requests can also be posted to community.jitsi.org.
Description
When I click on «Start recording» in the Jitsi-Meet UI I get a «Preparing recording meeting…» forever.
Current behavior
Aug 13 21:30:23 meet2 launch.sh[6121]: Aug 13, 2020 9:30:23 PM org.jitsi.jibri.api.xmpp.XmppApi$handleStartJibriIq$1 run
Aug 13 21:30:23 meet2 launch.sh[6121]: SEVERE: Error starting Jibri service : java.lang.ExceptionInInitializerError with stack:
Aug 13 21:30:23 meet2 launch.sh[6121]: org.jitsi.jibri.service.impl.FileRecordingJibriService.<init>(FileRecordingJibriService.kt:105)
Aug 13 21:30:23 meet2 launch.sh[6121]: org.jitsi.jibri.JibriManager.startFileRecording(JibriManager.kt:134)
Aug 13 21:30:23 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi.handleStartService(XmppApi.kt:281)
Aug 13 21:30:23 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi.access$handleStartService(XmppApi.kt:67)
Aug 13 21:30:23 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi$handleStartJibriIq$1.run(XmppApi.kt:191)
Aug 13 21:30:23 meet2 launch.sh[6121]: java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
Aug 13 21:30:23 meet2 launch.sh[6121]: java.util.concurrent.FutureTask.run(FutureTask.java:266)
Aug 13 21:30:23 meet2 launch.sh[6121]: java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
Aug 13 21:30:23 meet2 launch.sh[6121]: java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
Aug 13 21:30:23 meet2 launch.sh[6121]: java.lang.Thread.run(Thread.java:748)
Aug 13 21:30:31 meet2 launch.sh[6121]: Aug 13, 2020 9:30:31 PM org.jitsi.jibri.api.xmpp.XmppApi handleJibriIq
Aug 13 21:30:31 meet2 launch.sh[6121]: INFO: Received JibriIq <iq to='focus@auth.meet2.opensuse.org/QCHwiOIt' from='jibribrewery@internal.auth.meet2.opensuse.org/focus' id='Zm9jdXNAYXV0aC5tZWV0Mi5vcGVuc3VzZS5vcmcvUUNId2lPSXQASVBQTlctOTU4ACZ8g5CBryA1WQTqQFBi+Sw=' type='set'><jibri xmlns='http://jitsi.org/protocol/jibri' action='stop'/></iq> from environment [MucClient id=meet2.opensuse.org hostname=meet2.opensuse.org]
Aug 13 21:30:31 meet2 launch.sh[6121]: Aug 13, 2020 9:30:31 PM org.jitsi.jibri.JibriManager stopService
Aug 13 21:30:31 meet2 launch.sh[6121]: INFO: Stopping the current service
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi handleJibriIq
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Received JibriIq <iq to='focus@auth.meet2.opensuse.org/QCHwiOIt' from='jibribrewery@internal.auth.meet2.opensuse.org/focus' id='Zm9jdXNAYXV0aC5tZWV0Mi5vcGVuc3VzZS5vcmcvUUNId2lPSXQASVBQTlctOTgyACZ8g5CBryA1WQTqQFBi+Sw=' type='set'><jibri xmlns='http://jitsi.org/protocol/jibri' action='start' recording_mode='file' room='desperatepenguinsfinishruthlessly@conference.meet2.opensuse.org' session_id='bzxciempjgioizwl' app_data='{"file_recording_metadata":{"share":true}}'/></iq> from environment [MucClient id=meet2.opensuse.org hostname=meet2.opensuse.org]
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi handleStartJibriIq
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Received start request
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi handleStartJibriIq
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Sending 'pending' response to start IQ
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi$handleStartJibriIq$1 run
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Starting service
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi handleStartService
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Parsed call url info: CallUrlInfo(baseUrl=https://meet2.opensuse.org, callName=desperatepenguinsfinishruthlessly, urlParams=[])
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.JibriManager startFileRecording
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Starting a file recording with params: FileRecordingRequestParams(callParams=CallParams(callUrlInfo=CallUrlInfo(baseUrl=https://meet2.opensuse.org, callName=desperatepenguinsfinishruthlessly, urlParams=[])), sessionId=bzxciempjgioizwl, callLoginParams=XmppCredentials(domain=recorder.meet2.opensuse.org, username=recorder, password=YOURSECRET3)) finalize script path: /usr/share/jitsi-jibri/finalize_recording.sh and recordings directory: /srv/recordings
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi$handleStartJibriIq$1 run
Aug 13 21:30:42 meet2 launch.sh[6121]: SEVERE: Error starting Jibri service : java.lang.NoClassDefFoundError: Could not initialize class org.jitsi.jibri.selenium.JibriSelenium with stack:
Aug 13 21:30:42 meet2 launch.sh[6121]: org.jitsi.jibri.service.impl.FileRecordingJibriService.<init>(FileRecordingJibriService.kt:105)
Aug 13 21:30:42 meet2 launch.sh[6121]: org.jitsi.jibri.JibriManager.startFileRecording(JibriManager.kt:134)
Aug 13 21:30:42 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi.handleStartService(XmppApi.kt:281)
Aug 13 21:30:42 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi.access$handleStartService(XmppApi.kt:67)
Aug 13 21:30:42 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi$handleStartJibriIq$1.run(XmppApi.kt:191)
Aug 13 21:30:42 meet2 launch.sh[6121]: java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
Aug 13 21:30:42 meet2 launch.sh[6121]: java.util.concurrent.FutureTask.run(FutureTask.java:266)
Aug 13 21:30:42 meet2 launch.sh[6121]: java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
Aug 13 21:30:42 meet2 launch.sh[6121]: java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
Aug 13 21:30:42 meet2 launch.sh[6121]: java.lang.Thread.run(Thread.java:748)
Expected Behavior
Recording works.
Possible Solution
I saw in the forums a lot of issues around Selenium. The error reporting around this is vague and could be improved. Both stacktraces we got above are not telling us anything.
I also did put in the first line of init
in JibriSelenium
a Logger.info()
but this is not put out anywhere. Thus I guess we fail before reaching it.
My wild guess is that this is caused by the follwing line: private val stateMachine = SeleniumStateMachine()
Also to verify that this is working I put in for Selenium the following Java System Property: -Dwebdriver.chrome.driver="/usr/local/bin/chromedriver"
it made no difference, the stacktrace stays the same.
When monitoring with htop I can see that chrome is never starting up as well as I never see the Selenium Server being started.
Steps to reproduce
We followed the install guide in the README. I was able to reproduce this both with Java 1.8 and the Jibri Tag 8.0 (old config) and Java 11 on Git HEAD (new config).
Environment details
OS: openSUSE Leap 15.2
Java:
meet2:~/repos/jibri # java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (IcedTea 3.16.0) (build 1.8.0_252-b09 suse-lp152.1.2-x86_64)
OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)
meet2:~/repos/jibri # javac -version
javac 1.8.0_252
Процесс установки и настройки сервиса видеоконференций Jitsi Meet был описан в одной из предыдущих заметок.
Указанная в той заметке конфигурация срвиса была лишена одной немаловажной возможности, а именно возможности вести видеозапись конференции.
За наличие этой возможности отвечает сервис Jibri (JItsi BRoadcasting Infrastructure). Его настройка и будет описана далее.
Специфика работы Jibri такова, что один экземпляр этой службы может записывать только одну конференцию. Это происходит из-за того, что при нажатии
кнопки «Начать запись» Jibri подключается к конференции как участник и после этого записывает видео. Чтобы решить эту проблему и не плодить
при этом серверы с Jibri будем использовать docker-контейнеры.
Напомню, что Jitsi Meet установлен на Ubuntu 18.04 с адресом meet.oldfag.ru. На этот же сервер установим Docker Comunity Edition, где и будем запускать контейнеры с Jibri, чтобы ресурсы сервера не простаивали.
Однако если запускать контейнеры на другой машине, то в последовательности действий абсолютно ничего не изменится.
Описание настройки, для удобства, разделю на следующие этапы:
— настройка Prosody
— настройка Jicofo
— настройка интерфейса Jitsi Meet
— настройка ОС, на которой установлен Jitsi Meet
— установка docker, запуск и настройка сервиса Jibri
Так как подходящего способа получить количество активных комнат на сервере я так и не нашёл, плагин для Prosody mod_muc_size мне победить не удалось,
а так же не нашлось способа контролировать проставивают ли сейчас экземпляры Jibri в контейнерах и останавливать таковые, то просто буду запускать 5
экземпляров службы, т.к. с вероятностью, близкой к 100%, на данном сервере не будет запущено более 5 видеоконференций одновременно.
Предполагается, что все команды выполняются от имени пользователя с повышенными полномочиями, например через
sudo -s
Инструкция по настройке служб Jitsi Meet для использования Jibri есть на GitHub Jitsi
Начнём с того, что настроим ядро всей системы — jabber-сервер Prosody.
Откроем файл конфигурации нашего сервера
nano /etc/prosody/conf.avail/meet.oldfag.ru.cfg.lua
и добавим ещё один виртуальный хост
VirtualHost "recorder.meet.oldfag.ru" modules_enabled = { "ping"; } authentication = "internal_plain"
а так же внесём изменения в уже существующую секцию
-- internal muc component Component "internal.auth.meet.oldfag.ru" "muc" storage = "none" modules_enabled = { "ping"; } admins = { "focus@auth.meet.oldfag.ru", "jvb@auth.meet.oldfag.ru" } muc_room_locking = false muc_room_default_public_jids = true muc_room_cache_size = 1000 <<==== вот эту строку добавляем
Создадим на Prosody двух локальных пользователей, одного для коммуникации с Jibri, отправки ему команд и получения его статуса — jibri,
второго для непосредственно подключения к конференциям и записи видео — recorder.
prosodyctl register jibri auth.meet.oldfag.ru jibri-auth-strong-pass prosodyctl register recorder recorder.meet.oldfag.ru jibri-recorder-strong-pass
Настройка закончена, перезапускаем службу для применения настроек.
systemctl restart prosody
Службу можно перезапустить так же и с использованием prosodyctl
prosodyctl restart
Переходим к настройке модератора конференций — Jicofo (JItsi COnference FOcus).
Откроем файл /etc/jitsi/jicofo/sip-communicator.properties и добавим строки
org.jitsi.jicofo.jibri.BREWERY=JibriBrewery@internal.auth.meet.oldfag.ru org.jitsi.jicofo.jibri.PENDING_TIMEOUT=90
Сохраним изменения и перезапустим службу
systemctl restart jicofo
В интерфейс Jitsi Meet нужно добавить кнопки для записи и трансляции видео, для этого открываем файл /etc/jitsi/meet/meet.oldfag.ru-config.js,
переходим в секцию Recording и меняем строки
на
fileRecordingsEnabled: true, liveStreamingEnabled: true,
а так же добавляем строку
hiddenDomain: 'recorder.meet.oldfag.ru',
Кроме изменения настроек сервисов, так же нужно добавить ALSA-loopback устройства в ОС, на которой запущен сервис Jitsi Meet.
Количество этих устройств должно быть не меньше количества экземпляров Jibri, которые планируется использовать. В данном случае их будет создано 5 штук.
Инструкция по их настройке есть на GitHub Jitsi.
Обновим установленные пакеты и установим дополнительные драйверы
apt update && apt upgrade -y apt install linux-image-extra-virtual -y
создадим 5 устройств для захвата
echo "options snd-aloop enable=1,1,1,1,1 index=0,1,2,3,4" > /etc/modprobe.d/alsa-loopback.conf
добавим загрузку модуля при старте системы
echo "snd-aloop" >> /etc/modules
и загрузим модуль ядра в текущем сеансе, без перезагрузки системы
modprobe snd_aloop
Проверим, что модуль загружен
lsmod | grep snd_aloop
Если всё хорошо, то ответ будет таким
snd_aloop 24576 0 snd_pcm 98304 1 snd_aloop snd 81920 3 snd_timer,snd_aloop,snd_pcm
А теперь последнее по очереди, но не по значению — насройка docker и запуск контейнеров Jibri.
Для начала установим docker согласно инструкции.
Добавим ключ безопасности репозитория
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
и сам репозиторий
add-apt-repository
"deb [arch=amd64] https://download.docker.com/linux/ubuntu
$(lsb_release -cs)
stable"
Обновим список доступных пакетов и установим необходимые
apt update && apt install docker-ce docker-ce-cli containerd.io docker-compose -y
После того, как всё установится можно проверить что всё работает, запустив тестовый контейнер
docker run hello-world
Образ будет загружен из Docker Hub и запущен, если всё хорошо, то в консоли отобразится сообщение
Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
Не забываем добавить автозагрузку
systemctl enable docker
Создадим каталог хранения конфигурационных файлов для контейнеров
mkdir /etc/jibri-docker
а в нём файл конфигурации контейнера
touch /etc/jibri-docker/jibri.yml
со следующим содержанием
version: '3' services: jibri: image: jitsi/jibri volumes: - ${CONFIG}/jibri:/config - /dev/shm:/dev/shm cap_add: - SYS_ADMIN - NET_BIND_SERVICE devices: - /dev/snd:/dev/snd environment: - XMPP_AUTH_DOMAIN - XMPP_INTERNAL_MUC_DOMAIN - XMPP_RECORDER_DOMAIN - XMPP_SERVER - XMPP_DOMAIN - JIBRI_XMPP_USER - JIBRI_XMPP_PASSWORD - JIBRI_BREWERY_MUC - JIBRI_RECORDER_USER - JIBRI_RECORDER_PASSWORD - JIBRI_RECORDING_DIR - JIBRI_FINALIZE_RECORDING_SCRIPT_PATH - JIBRI_STRIP_DOMAIN_JID - JIBRI_LOGS_DIR - DISPLAY=:0 - TZ
В yml-файле не должно быть табуляций, все отступы создаются только пробелами.
Тут же создадим файл с переменными окружения
touch /etc/jibri-docker/.env
который будет содержать значения имён и паролей пользователей prosody, созданных ранее, адреса подключения и другие параметры.
XMPP_AUTH_DOMAIN=auth.meet.oldfag.ru XMPP_INTERNAL_MUC_DOMAIN=internal.auth.meet.oldfag.ru XMPP_RECORDER_DOMAIN=recorder.meet.oldfag.ru XMPP_SERVER=meet.oldfag.ru XMPP_DOMAIN=meet.oldfag.ru JIBRI_XMPP_USER=jibri JIBRI_XMPP_PASSWORD=jibri-auth-strong-pass JIBRI_BREWERY_MUC=jibribrewery JIBRI_RECORDER_USER=recorder JIBRI_RECORDER_PASSWORD=jibri-recorder-strong-pass JIBRI_RECORDING_DIR=/config/recordings JIBRI_FINALIZE_RECORDING_SCRIPT_PATH=/config/finalize.sh JIBRI_STRIP_DOMAIN_JID=conference JIBRI_LOGS_DIR=/config/logs DISPLAY=:0=
Пробуем запустить контейнер
cd /etc/jibri-docker docker-compose -f jibri.yml up
Если ufw активен, то тут можно будет увидеть ошибку
org.jivesoftware.smack.SmackException$ConnectionException: The following addresses failed: 'meet.oldfag.ru:5222' failed because: meet.oldfag.ru/192.168.1.147 exception: java.net.SocketTimeoutException: connect timed out
Останавливаем контейнер (Ctlr+C).
Добавляем правило для 5222 порта, это порт, используемый Jicofo
ufw allow 5222
Запускаем контейнер снова. Если всё хорошо, то в консоли можно будет увидеть
jibri_1 | 2020-10-22 09:48:44.648 INFO: [27] org.jitsi.xmpp.mucclient.MucClient.log() Joined MUC: jibribrewery@internal.auth.meet.oldfag.ru
Опять останавливаем контейнер и переходим к тому, что будет запущено 5 контейнеров, для одновременной записи 5 конференций. Если
нужно больше 5, то нужно не забыть кроме увеличения количества контейнеров увеличить количество ALSA-loopback устройств на сервере Jitsi.
Запустить несколько контейнеров сразу можно с помощью ключа —scale
docker-compose -f jibri.yml up --scale jibri=5 -d
jibri после ключа —scale в этой команде — имя службы, указанное в yml-файле, ключ -d нужен для того, чтобы контейнер запустился
без вывода всего и вся в консоль.
После этой команды будет запущено 5 контейнеров, но при этом на Jitsi будет доступна запись только одной конференции одновременно. Это происходит
из-за того, что для каждого экземпляра Jibri нужно указать своё ALSA-loopback устройство.
Чтобы это сделать выполним команды
docker exec jibridocker_jibri_1 sed -i 's/Loopback/0/g' /home/jibri/.asoundrc docker exec jibridocker_jibri_2 sed -i 's/Loopback/1/g' /home/jibri/.asoundrc docker exec jibridocker_jibri_3 sed -i 's/Loopback/2/g' /home/jibri/.asoundrc docker exec jibridocker_jibri_4 sed -i 's/Loopback/3/g' /home/jibri/.asoundrc docker exec jibridocker_jibri_5 sed -i 's/Loopback/4/g' /home/jibri/.asoundrc
и перезапустим контейнеры
docker restart jibridocker_jibri_1 jibridocker_jibri_2 jibridocker_jibri_3 jibridocker_jibri_4 jibridocker_jibri_5
Команды настройки устройств ALSA-loopback и перезапуска контейнеров лучше записать в отдельный исполняемый файл, т.к. они могут понадобится при
неосторожном удалении контейнеров или обновлении образа Jibri из Docker Hub.
Чтобы контейнеры поднимались при старте системы нужно выполнить команду
docker update --restart always <CONTAINER ID 1> <CONTAINER ID 2> ... <CONTAINER ID 5>
Идентификатор контейнера можно узнать выполнив команду
docker ps -a
Чтобы остановить контейнеры, если это необходимо, нужно использовать команду
docker-compose -f jibri.yml stop
а не
docker-compose -f jibri.yml down
т.к. последняя не только остановит контейнеры, но и удалит их, а следовательно и конфигурацию устройств в них.
Всё готово. Можно создать конференцию, открыть меню конференции, нажав на три точки в правом нижнем углу, выбрать пункт «Начать запись» и
услышать заветное: «Recording is on.»
Записи видеоконференций хранятся в /jibri/recordings/. Для постобработки записи (перемещение, публикация и т.д.) можно создать
скрипт /jibri/finalize.sh, его имя может быть любым, но оно должно быть указано в /etc/jibri-docker/.env в
параметре JIBRI_FINALIZE_RECORDING_SCRIPT_PATH. Его пример
можно найти на GitHub Jitsi
Я использовал это руководство https://github.com/jitsi/jibri и это видео https://www.youtube.com/watch?v=OHHoqKCjJ0E 2
Установить джибри
Но я не могу начать запись
На стороне Джитси
В файле /etc/prosody/conf.d/osboxes.osboxes.demoanuswadh.info.cfg.lua
- Добавляю пользователей для jibri, записываю и использую prosodyctl
- Добавлены компоненты internal.auth и рекордер.
В файле /etc/jitsi/meet/osboxes.demoanuswadh.info-config.js
- Включено fileRecordingsEnabled: ture
- Добавлен скрытый домен
В файле /etc/jitsi/jicofo/sip-communicator.properties
- org.jitsi.jicofo.jibri.BREWERY=JibriBrewery@internal.auth.osboxes.demoanuswadh.info
- org.jitsi.jicofo.jibri.PENDING_TIMEOUT=90
Это последние сто строк лога — log.0.txt
ava:312)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:744)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:369)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:852)
at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:278)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:138)
at org.eclipse.jetty.server.Server.start(Server.java:415)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:108)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
at org.eclipse.jetty.server.Server.doStart(Server.java:382)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.jitsi.jibri.MainKt.launchHttpServer(Main.kt:173)
at org.jitsi.jibri.MainKt.main(Main.kt:158)
Caused by: java.lang.ClassNotFoundException: javax.activation.DataSource
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
… 66 more
MultiException stack 2 of 2
java.lang.IllegalArgumentException: Errors were discovered while reifying SystemDescriptor(
implementation=org.glassfish.jersey.message.internal.DataSourceProvider
contracts={javax.ws.rs.ext.MessageBodyReader,javax.ws.rs.ext.MessageBodyWriter}
scope=javax.inject.Singleton
qualifiers={}
descriptorType=CLASS
descriptorVisibility=NORMAL
metadata=
rank=0
loader=null
proxiable=null
proxyForSameScope=null
analysisName=null
id=106
locatorId=1
identityHashCode=1778422985
reified=false)
at org.jvnet.hk2.internal.SystemDescriptor.reify(SystemDescriptor.java:705)
at org.jvnet.hk2.internal.ServiceLocatorImpl.reifyDescriptor(ServiceLocatorImpl.java:464)
at org.jvnet.hk2.internal.ServiceLocatorImpl.narrow(ServiceLocatorImpl.java:2310)
at org.jvnet.hk2.internal.ServiceLocatorImpl.access$1200(ServiceLocatorImpl.java:128)
at org.jvnet.hk2.internal.ServiceLocatorImpl$9.compute(ServiceLocatorImpl.java:1395)
at org.jvnet.hk2.internal.ServiceLocatorImpl$9.compute(ServiceLocatorImpl.java:1390)
at org.glassfish.hk2.utilities.cache.internal.WeakCARCacheImpl.compute(WeakCARCacheImpl.java:128)
at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetAllServiceHandles(ServiceLocatorImpl.java:1452)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getAllServiceHandles(ServiceLocatorImpl.java:1377)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getAllServiceHandles(ServiceLocatorImpl.java:1366)
at org.glassfish.jersey.inject.hk2.AbstractHk2InjectionManager.getAllServiceHolders(AbstractHk2InjectionManager.java:158)
at org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager.getAllServiceHolders(ImmediateHk2InjectionManager.java:54)
at org.glassfish.jersey.internal.inject.Providers.getServiceHolders(Providers.java:329)
at org.glassfish.jersey.internal.inject.Providers.getProviders(Providers.java:157)
at org.glassfish.jersey.message.internal.MessageBodyFactory.initialize(MessageBodyFactory.java:265)
at org.glassfish.jersey.message.internal.MessageBodyFactory$MessageBodyWorkersConfigurator.postInit(MessageBodyFactory.java:136)
at org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$2(ApplicationHandler.java:372)
at java.base/java.util.Arrays$ArrayList.forEach(Arrays.java:4390)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:372)
at org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$1(ApplicationHandler.java:316)
at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:256)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:315)
at org.glassfish.jersey.server.ApplicationHandler.(ApplicationHandler.java:282)
at org.glassfish.jersey.servlet.WebComponent.(WebComponent.java:335)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:178)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:370)
at javax.servlet.GenericServlet.init(GenericServlet.java:244)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:671)
at org.eclipse.jetty.servlet.ServletHolder.initialize(ServletHolder.java:428)
at org.eclipse.jetty.servlet.ServletHandler.lambda$initialize$0(ServletHandler.java:750)
at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:744)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:369)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:852)
at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:278)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:138)
at org.eclipse.jetty.server.Server.start(Server.java:415)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:108)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
at org.eclipse.jetty.server.Server.doStart(Server.java:382)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.jitsi.jibri.MainKt.launchHttpServer(Main.kt:173)
at org.jitsi.jibri.MainKt.main(Main.kt:158)
2020-04-18 19:06:12.543 SEVERE: [21] org.jitsi.xmpp.mucclient.MucClientManager.log() Failed to initialize and start a MucClient:
org.jivesoftware.smack.SmackException$ConnectionException: The following addresses failed: ‘osboxes.demoanuswadh.info:5222’ failed because: osboxes.demoanuswadh.info/77.525.75.82 exception: java.net.ConnectException: Connection refused (Connection refused)
at org.jivesoftware.smack.SmackException$ConnectionException.from(SmackException.java:278)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectUsingConfiguration(XMPPTCPConnection.java:619)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectInternal(XMPPTCPConnection.java:902)
at org.jivesoftware.smack.AbstractXMPPConnection.connect(AbstractXMPPConnection.java:383)
at org.jitsi.xmpp.mucclient.MucClient.initializeConnectAndJoin(MucClient.java:277)
at org.jitsi.xmpp.mucclient.MucClientManager.lambda$addMucClient$0(MucClientManager.java:152)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
2020-04-18 19:06:42.348 WARNING: [30] org.jivesoftware.smackx.ping.PingManager.pingServerIfNecessary() XMPPConnection was not authenticated
2020-04-18 19:22:59.687 INFO: [17] org.jitsi.jibri.api.http.internal.InternalHttpApi.gracefulShutdown() Jibri gracefully shutting down
/etc/jitsi/jibri/config.json
{
// NOTE: this is a *SAMPLE* config file, it will need to be configured with
// values from your environment
// Where recording files should be temporarily stored
"recording_directory":"/xxxxxxxxxx/xxxxxxxxx/recordings",
// The path to the script which will be run on completed recordings
"finalize_recording_script_path": "/path/to/finalize_recording.sh",
"xmpp_environments": [
{
// A friendly name for this environment which can be used
// for logging, stats, etc.
"name": "prod environment",
// The hosts of the XMPP servers to connect to as part of
// this environment
"xmpp_server_hosts": [
"osboxes.demoanuswadh.info"
],
// The xmpp domain we'll connect to on the XMPP server
"xmpp_domain": "osboxes.demoanuswadh.info",
// Jibri will login to the xmpp server as a privileged user
"control_login": {
// The domain to use for logging in
"domain": "auth.osboxes.demoanuswadh.info",
// The credentials for logging in
"username": "jibri",
"password": "xxxxxxxxxxxxxxxxxx"
},
// Using the control_login information above, Jibri will join
// a control muc as a means of announcing its availability
// to provide services for a given environment
"control_muc": {
"domain": "internal.auth.osboxes.demoanuswadh.info",
"room_name": "JibriBrewery",
"nickname": "jibri-nickname"
},
// All participants in a call join a muc so they can exchange
// information. Jibri can be instructed to join a special muc
// with credentials to give it special abilities (e.g. not being
// displayed to other users like a normal participant)
"call_login": {
"domain": "recorder.osboxes.demoanuswadh.info",
"username": "recorder",
"password": "xxxxxxxxxxxxxxxxxxxxxx"
},
// When jibri gets a request to start a service for a room, the room
// jid will look like:
// roomName@optional.prefixes.subdomain.xmpp_domain
// We'll build the url for the call by transforming that into:
// https://xmpp_domain/subdomain/roomName
// So if there are any prefixes in the jid (like jitsi meet, which
// has its participants join a muc at conference.xmpp_domain) then
// list that prefix here so it can be stripped out to generate
// the call url correctly
"room_jid_domain_string_to_strip_from_start": "conference.",
// The amount of time, in minutes, a service is allowed to continue.
// Once a service has been running for this long, it will be
// stopped (cleanly). A value of 0 means an indefinite amount
// of time is allowed
"usage_timeout": "0"
}
]
}
Я буду признателен за любую помощь. заранее спасибо
3 ответа
В вашем логе написано, что в соединении отказано.
2020-04-18 19:06:12.543 SEVERE: [21] org.jitsi.xmpp.mucclient.MucClientManager.log() Failed to initialize and start a MucClient:[...] failed because: osboxes.demoanuswadh.info/77.525.75.82 exception: java.net.ConnectException: Connection refused (Connection refused)
Подтвердите пользователя, домен и пароль в jitsi. Когда будете готовы, удалите log.0.txt или переименуйте его и перезапустите службу jibri, чтобы получить чистый журнал.
1
AndreaTaroni86
8 Май 2020 в 20:12
Перед установкой Jibri вы должны включить порт 5222
на сервере Jitsi. Лучше, если вы сможете использовать сервер Debian только для Jibri. Не сервер Jitsi. Потому что сервисы FFmpeg and chromium
могут без проблем работать на сервере Debian.
0
Nipuna Akalana Perera
18 Фев 2021 в 14:18
2020-04-18 19:06:12.543 SEVERE: [21] org.jitsi.xmpp.mucclient.MucClientManager.log() Failed to initialize and start a MucClient:
org.jivesoftware.smack.SmackException$ConnectionException: The following addresses failed: ‘osboxes.demoanuswadh.info:5222’ failed because: osboxes.demoanuswadh.info/77.525.75.82 exception: java.net.ConnectException: Connection refused (Connection refused)
В вашем журнале указано, что jibri подключается к osboxes.demoanuswadh.info (будет ли он разрешен к локальному хосту или общедоступному IP-адресу?)
Если вы установили jitsi-meet и jibri на один и тот же хост, убедитесь, что osboxes.demoanuswadh.info должен быть разрешен к localhost.
Если вы установили на другом компьютере в той же подсети, osboxes.demoanuswadh.info должен быть разрешен к частному IP-адресу.
Если вы установили на другой компьютер в той же подсети, osboxes.demoanuswadh.info должен быть разрешен к общедоступному IP-адресу.
В последних 2 случаях убедитесь, что ваша просодия прослушивает порт 5222, привязанный к 0.0.0.0, а также разрешите доступ к брандмауэру с помощью ufw (брандмауэр Ubuntu)
0
shooding
17 Июн 2021 в 06:32
Привет! Меня зовут Роман. Я back-end разработчик в digital-агентстве MACHAON. Мы занимаемся разработкой и развитием цифровых решений для b2b и EdTech.
В прошлой статье я рассказывал, как мы реализовали на нашем проекте «онлайн-школа Programica» видеотрансляции с помощью open-source решения Jitsi Meet.
Сегодня расскажу и дам пошаговую инструкцию, как поднять сервер с Jibri, чтобы транслировать и вести запись видеоконференций.
Jibri предоставляет услуги для записи или потоковой передачи конференции Jitsi Meet. Он работает, запуская экземпляр Chrome, отображаемый в виртуальном буфере кадра, и захватывая и кодируя вывод с помощью ffmpeg. Он предназначен для запуска на отдельной машине (или виртуальной машине), при этом никакие другие приложения не используют дисплей или аудиоустройства. На одном экземпляре jibri поддерживается запись только одной видеоконференции за раз.
Простыми словами, Jibri — это способ записи конференции Jitsi. Ниже рассказывается, как можно установить и использовать Jibri на одном или нескольких выделенных серверах либо с использование docker-контейнеров.
Перед тем как переходить к настройке, убедитесь, что Jitsi установлен и работоспособен.
nПри настройке будет использована константа `your-domain` — это доменное имя Jitsi или его ip-адрес. Везде где она встречается требуется заменить.n
Настройки prosody
Настроим prosody для работы с Jibri.
В конфигурации prosody `/etc/prosody/conf.avail/.cfg.lua`
проверьте наличие компонента или добавьте его
Component "internal.auth." "muc"rn modules_enabled = {rn "ping";rn }rn -- Используйте "none" для prosody 0.10 и "memory" для prosody 0.11rn storage = "memory"rn muc_room_cache_size = 1000
nЕсли данный компонент уже прописан, обязательно проверьте наличие параметра `muc_room_cache_size` В противном случае это не заработает.n
А также создадим еще один виртуальный хост:
VirtualHost "recorder."rn modules_enabled = {rn "ping";rn }rn authentication = "internal_plain"
Настройте две учетные записи, которые будет использовать Jibri:
jibri — для коммуникации с Jibri, отправки ему команд и получения его статуса;
recorder — для непосредственно подключения к конференциям и записи видео.
prosodyctl register jibri auth.. {JIBRI_AUTH_PASSWORD}rnprosodyctl register recorder recorder. {JIBRI_RECORDER_PASSWORD}
nКонстанты `JIBRI_AUTH_PASSWORD` и `JIBRI_RECORDER_PASSWORD` будут использованы далее. Их нужно выбрать на свое усмотрение — это пароли для служебных пользователей `jibri` и `recorder` соответственно. Рекомендуется выбирать разные пароли для каждого из этих пользователей. Рекомендуемая длина — 12 символов, включая строчные и заглавные буквы латинского алфавита, цифры и специальные символы.n
Настройка prosody закончена, перезапускаем службу для изменения настроек.
sudo systemctl restart prosody
Настройки jicofo
Отредактируйте `/etc/jitsi/jicofo/jicofo.conf`
, установите соответствующий MUC для поиска контроллеров Jibri. Это должен быть тот же MUC, что и в файле config.json jibri. Перезапустите Jicofo после установки этого свойства. Также предлагается установить время ожидания ожидания на 90 секунд, чтобы дать Jibri некоторое время для запуска, прежде чем попытка записи будет интерпретирована как сбой.
jicofo {rn ...rn jibri {rn brewery-jid: "JibriBrewery@internal.auth."rn pending-timeout: 90 secondsrn }rn ...rn}
sudo systemctl restart jicofo
Настройка конференции
Отредактируйте файл `/etc/jitsi/meet/-config.js`
, добавьте/установите следующие свойства:
fileRecordingsEnabled: true, // Если вам требуется записывать конференцию в файлrnliveStreamingEnabled: true, // Если вам требуется вести прямую трансляциюrnhiddenDomain: 'recorder.',
Также убедитесь, что в конфигурации вашего интерфейса (`/usr/share/jitsi-meet/interface_config.js`
по умолчанию) массив `TOOLBAR_BUTTONS`
содержит значение записи, если нужно показать кнопку записи файла, и значение прямой трансляции, если нужно показать кнопку прямого эфира. Как только запись будет включена в `-config.js`
, кнопка записи станет доступна в пользовательском интерфейсе. Однако до тех пор, пока Jicofo не увидит действительный jibri, при нажатии будет отображаться сообщение «Запись в настоящее время недоступна». После успешного подключения jibri пользователю вместо этого будет предложено ввести ключ потока. Примечание. Обязательно обновите `config.json`
Jibri соответствующим образом, чтобы он соответствовал любой конфигурации, выполненной выше.
Установка Jibri с использованием нескольких серверов
Этот способ взаимодействия с Jibri наиболее простой и имеет свои плюсы и минусы. Плюс в простоте настройки, более гибкой настройке каждого экземпляра jibri. Если требуется записывать только одну конференцию в один момент времени, то рекомендуется этот способ. Минусы в масштабируемости, так как под каждый экземпляр требуется заводить новый сервер. И если требуется записывать несколько конференций одновременно, то следует воспользоваться следующим способом.
Модуль ALSA
Сначала убедитесь, что модуль обратной связи ALSA доступен. Дополнительные модули (включая loopback ALSA) можно установить в Ubuntu, используя имя пакета linux-image-extra-virtual.
# Установка модуля при загрузкеrnsudo echo "snd_aloop" >> /etc/modulesrn# Загрузка модуля в работающее ядроrnsudo modprobe snd_aloop rntrn# Убедитесь что модуль доступенrnsudo lsmod | grep snd_aloop rn# Выводrnsnd_aloop 24576 0rnsnd_pcm 106496 1 snd_alooprnsnd 90112 3 snd_timer,snd_aloop,snd_pcm
Стабильная версия Google Chrome и драйвер Chrome
Следует использовать последнюю стабильную сборку Google Chrome. Его можно установить напрямую через apt, но ручные инструкции по его установке следующие:
sudo curl https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo sh -c 'gpg --dearmor > /usr/share/keyrings/google-chrome-keyring.gpg'rnsudo echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.listrnsudo apt-get -y updaternsudo apt-get -y install google-chrome-stable
Добавьте файл управляемых политик Chrome и задайте для CommandLineFlagSecurityWarningsEnabled значение false. Это скроет предупреждения в Chrome. Вы можете установить его так:
sudo mkdir -p /etc/opt/chrome/policies/managedrnsudo echo '{ "CommandLineFlagSecurityWarningsEnabled": false }' >>/etc/opt/chrome/policies/managed/managed_policies.json
Chromedriver также требуется и может быть установлен следующим образом:
CHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`rnwget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/rnunzip ~/chromedriver_linux64.zip -d ~/rnrm ~/chromedriver_linux64.ziprnsudo mv -f ~/chromedriver /usr/local/bin/chromedriverrnsudo chown root:root /usr/local/bin/chromedriverrnsudo chmod 0755 /usr/local/bin/chromedriver
Дополнительные необходимые пакеты
Необходимые зависимости см. в управляющем файле debian. Их можно установить с помощью следующей команды:
sudo apt-get install default-jre-headless ffmpeg curl alsa-utils icewm xdotool xserver-xorg-video-dummy ruby-hocon
Установка Jibri
Пакеты Jibri можно найти в стабильном репозитории на сайте downloads.jitsi.org. Сначала установите ключ репозитория Jitsi в свою систему:
curl https://download.jitsi.org/jitsi-key.gpg.key | sudo sh -c 'gpg --dearmor > /usr/share/keyrings/jitsi-keyring.gpg'
Создайте файл `sources.list.d`
с репозиторием:
echo 'deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] https://download.jitsi.org stable/' | sudo tee /etc/apt/sources.list.d/jitsi-stable.list > /dev/null
Установите последнюю версию jibri:
sudo apt-get updaternsudo apt-get install jibri
User, group
Убедитесь, что пользователь jibri находится в правильных группах, чтобы получить полный доступ к аудио- и видеоустройствам. Пример: «adm», «audio», «video», «plugdev».
sudo usermod -aG adm,audio,video,plugdev jibri
Config files
Отредактируйте файл `jibri.conf`
(установленный по умолчанию в `/etc/jitsi/jibri/jibri.conf`
) соответствующим образом. Вы можете посмотреть в reference.conf значения по умолчанию и пример того, как настроить `jibri.conf`
. Переопределите только те значения, которые требуется изменить.
jibri {rn api {rn xmpp {rn environments = [rn {rn name = ""rn xmpp-server-hosts = [""],rn xmpp-domain = ""rn control-login {rn domain = "auth."rn username = "jibri"rn password = "{JIBRI_AUTH_PASSWORD}"rn port = 5222rn }rn control-muc {rn domain = "internal.auth."rn room-name = "JibriBrewery"rn nickname = "{JIBRI_RECORDER_NICKNAME}"rn }rn call-login {rn domain = "recorder."rn username = "recorder"rn password = "{JIBRI_RECORDER_PASSWORD}"rn }rn strip-from-room-domain = "conference."rn trust-all-xmpp-certs = truern usage-timeout = 0rn }rn ]rn }rn }rn # Секция recording не является обязательной и может быть удаленаrn recording {rn recordings-directory = "/path/to/recordings"rn finalize-script = "/path/to/finalize_script.sh"rn }rn}
n`JIBRI_RECORDER_NICKNAME` можно выбрать на свое усмотрение. Это имя будет использоваться при присоединении Jibri к конференции.n
Чтобы задать собственную папку для сохранения записей, ее требуется создать и дать права на доступ к папке.
mkdir /path/to/recordingsrnchown jibri:jibri /path/to/recordingsrnchmod 775 /path/to/recordings
Чтобы добавить скрипт, который будет выполняться после того, как запись будет сформирована, также требуется создать данный скрипт и установить нужные права.
nano /path/to/finalize_script.shrnchown jibri:jibri /path/to/finalize_script.shrnchmod 755 /path/to/finalize_script.sh
Логирование
По умолчанию Jibri регистрируется в `/var/log/jitsi/jibri`
. Если вы не устанавливаете через пакет debian, вам нужно убедиться, что этот каталог существует (или изменить местоположение, в которое Jibri ведет журналы, отредактировав конфигурацию журнала).
Установка jibri с использованием docker-контейнеров
Чтобы решить проблему с масштабируемостью, мы воспользуемся docker и обернем каждый экземпляр ijbri в отдельный контейнер. Таким образом мы сможем динамически добавлять и убирать экземпляры, если того требует сервис, который использует запись видеоконференций.
Требования
У вас должен быть установлен и запущен работоспособный docker.
Модуль ALSA
Сначала убедитесь, что модуль обратной связи ALSA доступен. Дополнительные модули (включая loopback ALSA) можно установить в Ubuntu, используя имя пакета linux-image-extra-virtual.
Так же добавим устройства ALSA-loopback. Количество этих устройств должно быть не меньше количества экземпляров Jibri, которые планируется использовать. В данном случае их будет создано 5 штук.
#Создадим 5 устройств для захватаrnsudo echo "options snd-aloop enable=1,1,1,1,1 index=0,1,2,3,4" > /etc/modprobe.d/alsa-loopback.confrntrn# Установка модуля при загрузкеrnsudo echo "snd_aloop" >> /etc/modulesrntrn# Загрузка модуля в работающее ядроrnsudo modprobe snd_aloop rntrn# Убедитесь что модуль доступенrnsudo lsmod | grep snd_aloop rn# Выводrnsnd_aloop 24576 0rnsnd_pcm 106496 1 snd_alooprnsnd 90112 3 snd_timer,snd_aloop,snd_pcm
Настройка docker
Создадим файл конфигурации
#Создадим каталог хранения конфигурационных файлов для контейнеровrnsudo mkdir /etc/jibri-dockerrnrn#Создадим файл конфигурации контейнераrnsudo nano /etc/jibri-docker/jibri.yml
со следующим содержимым:
version: '3'rnrnservices:rn jibri:rn image: jitsi/jibrirn volumes:rn - ${CONFIG}/jibri:/configrn - /dev/shm:/dev/shmrn cap_add:rn - SYS_ADMINrn - NET_BIND_SERVICErn devices:rn - /dev/snd:/dev/sndrn environment:rn - XMPP_AUTH_DOMAINrn - XMPP_INTERNAL_MUC_DOMAINrn - XMPP_RECORDER_DOMAINrn - XMPP_SERVERrn - XMPP_DOMAINrn - JIBRI_XMPP_USERrn - JIBRI_XMPP_PASSWORDrn - JIBRI_BREWERY_MUCrn - JIBRI_RECORDER_USERrn - JIBRI_RECORDER_PASSWORDrn - JIBRI_RECORDING_DIRrn - JIBRI_FINALIZE_RECORDING_SCRIPT_PATHrn - JIBRI_STRIP_DOMAIN_JIDrn - JIBRI_LOGS_DIRrn - DISPLAY=:0rn - TZrn```
Тут же создадим файл с переменными окружения.
sudo nano /etc/jibri-docker/.env
со следующим содержимым:
# JIBRI CONFIGrnrn# Internal XMPP domain for authenticated servicesrnXMPP_AUTH_DOMAIN=auth.rnrn# XMPP domain for the internal MUC used for jibri, jigasi and jvb poolsrnXMPP_INTERNAL_MUC_DOMAIN=internal.auth.rnrn# XMPP domain for the jibri recorderrnXMPP_RECORDER_DOMAIN=recorder.rnrn# Internal XMPP serverrnXMPP_SERVER=rnrn# Internal XMPP domainrnXMPP_DOMAIN=rnrn# XMPP user for Jibri client connectionsrnJIBRI_XMPP_USER=jibrirnrn# XMPP password for Jibri client connectionsrnJIBRI_XMPP_PASSWORD={JIBRI_AUTH_PASSWORD}rnrn# MUC name for the Jibri poolrnJIBRI_BREWERY_MUC=jibribreweryrnrn# XMPP recorder user for Jibri client connectionsrnJIBRI_RECORDER_USER=recorderrnrn# XMPP recorder password for Jibri client connectionsrnJIBRI_RECORDER_PASSWORD={JIBRI_RECORDER_PASSWORD}rnrn# Directory for recordings inside Jibri containerrnJIBRI_RECORDING_DIR=/config/recordingsrnrn# The finalizing script. Will run after recording is completernJIBRI_FINALIZE_RECORDING_SCRIPT_PATH=/config/finalize.shrnrn# When jibri gets a request to start a service for a room, the roomrn# jid will look like: roomName@optional.prefixes.subdomain.xmpp_domainrn# We'll build the url for the call by transforming that into:rn# https://xmpp_domain/subdomain/roomNamern# So if there are any prefixes in the jid (like jitsi meet, whichrn# has its participants join a muc at conference.xmpp_domain) thenrn# list that prefix here so it can be stripped out to generatern# the call url correctlyrnJIBRI_STRIP_DOMAIN_JID=conferencernrn# Directory for logs inside Jibri containerrnJIBRI_LOGS_DIR=/config/logsrnrnDISPLAY=:0=
Пробуем запустить контейнер.
cd /etc/jibri-dockerrnsudo docker-compose -f jibri.yml up
nЕсли ufw активен, то может возникнуть ошибка. Для этого требуется открыть порт 5222 ufw allow 5222n
Если все хорошо, останавливаем контейнер и переходим к тому, что будет запущено 5 контейнеров, для одновременной записи 5 конференций. Если нужно больше 5, то нужно не забыть кроме увеличения количества контейнеров, увеличить количество ALSA-loopback устройств на сервере Jibri.
Запустим несколько контейнеров.
docker-compose -f jibri.yml up --scale jibri=5 -d
После этой команды будет запущено 5 контейнеров, но при этом на Jitsi будет доступна запись только одной конференции одновременно. Это происходит из-за того, что для каждого экземпляра Jibri нужно указать своё ALSA-loopback устройство.
Чтобы это сделать выполним команды:
docker exec jibridocker_jibri_1 sed -i 's/Loopback/0/g' /home/jibri/.asoundrcrndocker exec jibridocker_jibri_2 sed -i 's/Loopback/1/g' /home/jibri/.asoundrcrndocker exec jibridocker_jibri_3 sed -i 's/Loopback/2/g' /home/jibri/.asoundrcrndocker exec jibridocker_jibri_4 sed -i 's/Loopback/3/g' /home/jibri/.asoundrcrndocker exec jibridocker_jibri_5 sed -i 's/Loopback/4/g' /home/jibri/.asoundrc
и перезапустим контейнеры
docker restart jibridocker_jibri_1 jibridocker_jibri_2 jibridocker_jibri_3 jibridocker_jibri_4 jibridocker_jibri_5
Чтобы облегчить работу с контейнерами, можно вынести команды настройки устройств ALSA-loopback и перезапуска в отдельный файл, так как они могут быть полезными.
#Чтобы остановить контейнеры используйтеrndocker-compose stoprnrn#Чтобы возобновить работу контейнеров, не забывая указывать количество требуемых контейнеров и выделять под них ALSA-loopback устройстваrndocker-compose -f jibri.yml up --scale jibri=5 -d
Благодарю за внимание! Надеюсь, был полезен. Если есть вопросы, пишите в комментариях, обсудим.
@aaronkvanmeerten @nightstryke
thanks for your help.
i have updated the config to below:
// The hosts of the XMPP servers to connect to as part of
// this environment
"xmpp_server_hosts": [
"onestar.cloud"
],
// The xmpp domain we'll connect to on the XMPP server
"xmpp_domain": "onestar.cloud",
// Jibri will login to the xmpp server as a privileged user
"control_login": {
// The domain to use for logging in
"domain": "auth.onestar.cloud",
// The credentials for logging in
"username": "jibri",
"password": "jibriauthpass"
},
// Using the control_login information above, Jibri will join
// a control muc as a means of announcing its availability
// to provide services for a given environment
"control_muc": {
"domain": "internal.auth.onestar.cloud",
"room_name": "2017",
"nickname": "jibri-nickname"
},
// All participants in a call join a muc so they can exchange
// information. Jibri can be instructed to join a special muc
// with credentials to give it special abilities (e.g. not being
// displayed to other users like a normal participant)
"call_login": {
"domain": "recorder.onestar.cloud",
"username": "recorder",
"password": "jibrirecorderpass"
},
// When jibri gets a request to start a service for a room, the room
// jid will look like:
// roomName@optional.prefixes.subdomain.xmpp_domain
// We'll build the url for the call by transforming that into:
// https://xmpp_domain/subdomain/roomName
// So if there are any prefixes in the jid (like jitsi meet, which
// has its participants join a muc at conference.xmpp_domain) then
// list that prefix here so it can be stripped out to generate
// the call url correctly
"room_jid_domain_string_to_strip_from_start": "conference.",
// The amount of time, in minutes, a service is allowed to continue.
// Once a service has been running for this long, it will be
// stopped (cleanly). A value of 0 means an indefinite amount
// of time is allowed
"usage_timeout": "0"
}
]
}
but it failed again if i started it with service command.
sudo systemctl status jibri.service
● jibri.service — Jibri Process
Loaded: loaded (/etc/systemd/system/jibri.service; disabled; vendor preset: enabled)
Active: inactive (dead)
May 25 13:44:18 ubuntu graceful_shutdown.sh[13762]: % Total % Received % Xferd Average Speed Time Time Time Current
May 25 13:44:18 ubuntu graceful_shutdown.sh[13762]: Dload Upload Total Spent Left Speed
May 25 13:44:18 ubuntu graceful_shutdown.sh[13762]: [149B blob data]
May 25 13:44:18 ubuntu systemd[1]: jibri.service: Control process exited, code=exited status=7
May 25 13:44:18 ubuntu systemd[1]: jibri.service: Unit entered failed state.
May 25 13:44:18 ubuntu systemd[1]: jibri.service: Failed with result ‘exit-code’.
May 25 13:44:18 ubuntu systemd[1]: jibri.service: Service hold-off time over, scheduling restart.
May 25 13:44:18 ubuntu systemd[1]: Stopped Jibri Process.
May 25 13:44:18 ubuntu systemd[1]: jibri.service: Start request repeated too quickly.
May 25 13:44:18 ubuntu systemd[1]: Failed to start Jibri Process.
ubuntu@ubuntu:/etc/jitsi/jibri$
i have tried to start it with scripts, there are logs below:
ubuntu@ubuntu:/etc/jitsi/jibri$ sudo /opt/jitsi/jibri/launch.sh
2018-05-25 13:45:32.982 INFO: [1] org.jitsi.jibri.Main.main() Using config file /etc/jitsi/jibri/config.json
2018-05-25 13:45:33.561 INFO: [1] org.jitsi.jibri.Main.loadConfig() Parsed config:
JibriConfig(recordingDirectory=/tmp/recordings, finalizeRecordingScriptPath=/path/to/finalize_recording.sh, xmppEnvironments=[XmppEnvironmentConfig(name=prod, xmppServerHosts=[onestar.cloud], xmppDomain=onestar.cloud, controlLogin=XmppCredentials(domain=auth.onestar.cloud, username=jibri, password=jibriauthpass), controlMuc=XmppMuc(domain=internal.auth.onestar.cloud, roomName=2017, nickname=jibri-nickname), sipControlMuc=null, callLogin=XmppCredentials(domain=recorder.onestar.cloud, username=recorder, password=jibrirecorderpass), stripFromRoomDomain=conference., usageTimeoutMins=0, trustAllXmppCerts=true)])
2018-05-25 13:45:33.599:INFO::main: Logging initialized @861ms
2018-05-25 13:45:33.626:WARN:oejsh.ContextHandler:main: o.e.j.s.ServletContextHandler@1603cd68{/,null,null} contextPath ends with /*
2018-05-25 13:45:33.626:WARN:oejsh.ContextHandler:main: Empty contextPath
2018-05-25 13:45:33.629:INFO:oejs.Server:main: jetty-9.2.z-SNAPSHOT
2018-05-25 13:45:33.910 WARNING: [1] org.glassfish.jersey.internal.inject.Providers.checkProviderRuntime() A provider org.jitsi.jibri.api.http.internal.InternalHttpApi registered in SERVER runtime does not implement any provider interfaces applicable in the SERVER runtime. Due to constraint configuration problems the provider org.jitsi.jibri.api.http.internal.InternalHttpApi will be ignored.
2018-05-25 13:45:33.999:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@1603cd68{/,null,AVAILABLE}
2018-05-25 13:45:34.007:INFO:oejs.ServerConnector:main: Started ServerConnector@438bad7c{HTTP/1.1}{0.0.0.0:3333}
2018-05-25 13:45:34.008:INFO:oejs.Server:main: Started @1271ms
2018-05-25 13:45:34.101 INFO: [1] org.jitsi.jibri.api.xmpp.XmppApi.start() Connecting to xmpp environment on onestar.cloud with config XmppEnvironmentConfig(name=prod, xmppServerHosts=[onestar.cloud], xmppDomain=onestar.cloud, controlLogin=XmppCredentials(domain=auth.onestar.cloud, username=jibri, password=jibriauthpass), controlMuc=XmppMuc(domain=internal.auth.onestar.cloud, roomName=2017, nickname=jibri-nickname), sipControlMuc=null, callLogin=XmppCredentials(domain=recorder.onestar.cloud, username=recorder, password=jibrirecorderpass), stripFromRoomDomain=conference., usageTimeoutMins=0, trustAllXmppCerts=true)
2018-05-25 13:45:34.107 INFO: [1] org.jitsi.jibri.api.xmpp.XmppApi.start() The trustAllXmppCerts config is enabled for this domain, all XMPP server provided certificates will be accepted
2018-05-25 13:45:34.268 INFO: [1] class org.jitsi.xmpp.mucclient.MucClient.connected() Xmpp connection status [auth.onestar.cloud]: connected
2018-05-25 13:45:34.290 INFO: [1] class org.jitsi.xmpp.mucclient.MucClient.authenticated() Xmpp connection status [auth.onestar.cloud]: authenticated
2018-05-25 13:45:34.303 INFO: [1] org.jitsi.jibri.api.xmpp.XmppApi.invoke() Jibri reports its status is now idle, publishing presence to connection prod
2018-05-25 13:45:34.304:WARN:oejsh.ContextHandler:main: o.e.j.s.ServletContextHandler@53692008{/,null,null} contextPath ends with /*
2018-05-25 13:45:34.305:WARN:oejsh.ContextHandler:main: Empty contextPath
2018-05-25 13:45:34.305:INFO:oejs.Server:main: jetty-9.2.z-SNAPSHOT
2018-05-25 13:45:34.332 WARNING: [1] org.glassfish.jersey.internal.inject.Providers.checkProviderRuntime() A provider org.jitsi.jibri.api.http.HttpApi registered in SERVER runtime does not implement any provider interfaces applicable in the SERVER runtime. Due to constraint configuration problems the provider org.jitsi.jibri.api.http.HttpApi will be ignored.
2018-05-25 13:45:34.356:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@53692008{/,null,AVAILABLE}
2018-05-25 13:45:34.356:INFO:oejs.ServerConnector:main: Started ServerConnector@3496655e{HTTP/1.1}{0.0.0.0:2222}
2018-05-25 13:45:34.357:INFO:oejs.Server:main: Started @1620ms
2018-05-25 13:46:05.251:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@332060d5{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.468:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@6d7efcc0{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.577:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@5f7d1e9e{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.630:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@4925f28f{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.646:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@63b91f1f{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.685:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@51bafb01{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.765:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@4971f6fd{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.801:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@678697b0{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:05.819:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@558575ee{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.206:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@4735f6d2{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.207:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@1087f13a{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.211:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@2739945a{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.314:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@12e77853{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.317:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@22841524{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.347:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@21dd014f{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.435:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@74b0410a{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.485:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@38067548{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.503:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@5f893a9f{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.556:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@32b0877f{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.617:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@13ecd4b0{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.657:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@70a80e75{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.700:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@5a5b649d{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.746:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@4084ea6a{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.846:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@1bd8cf7e{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.849:WARN:oejh.HttpParser:qtp466577384-35: badMessage: 400 No URI for HttpChannelOverHttp@7357aa65{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.896:WARN:oejh.HttpParser:qtp466577384-37: badMessage: 400 No URI for HttpChannelOverHttp@42abea6b{r=0,c=false,a=IDLE,uri=-}
2018-05-25 13:46:06.938:WARN:oejh.HttpParser:qtp466577384-36: badMessage: 400 No URI for HttpChannelOverHttp@52466233{r=0,c=false,a=IDLE,uri=-}
could you check it again ?is there any mistake over there ?
This Issue tracker is only for reporting bugs and tracking code related issues.
Before posting, please make sure you check community.jitsi.org to see if the same or similar bugs have already been discussed. General questions, installation help, and feature requests can also be posted to community.jitsi.org.
Description
When I click on «Start recording» in the Jitsi-Meet UI I get a «Preparing recording meeting…» forever.
Current behavior
Aug 13 21:30:23 meet2 launch.sh[6121]: Aug 13, 2020 9:30:23 PM org.jitsi.jibri.api.xmpp.XmppApi$handleStartJibriIq$1 run
Aug 13 21:30:23 meet2 launch.sh[6121]: SEVERE: Error starting Jibri service : java.lang.ExceptionInInitializerError with stack:
Aug 13 21:30:23 meet2 launch.sh[6121]: org.jitsi.jibri.service.impl.FileRecordingJibriService.<init>(FileRecordingJibriService.kt:105)
Aug 13 21:30:23 meet2 launch.sh[6121]: org.jitsi.jibri.JibriManager.startFileRecording(JibriManager.kt:134)
Aug 13 21:30:23 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi.handleStartService(XmppApi.kt:281)
Aug 13 21:30:23 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi.access$handleStartService(XmppApi.kt:67)
Aug 13 21:30:23 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi$handleStartJibriIq$1.run(XmppApi.kt:191)
Aug 13 21:30:23 meet2 launch.sh[6121]: java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
Aug 13 21:30:23 meet2 launch.sh[6121]: java.util.concurrent.FutureTask.run(FutureTask.java:266)
Aug 13 21:30:23 meet2 launch.sh[6121]: java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
Aug 13 21:30:23 meet2 launch.sh[6121]: java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
Aug 13 21:30:23 meet2 launch.sh[6121]: java.lang.Thread.run(Thread.java:748)
Aug 13 21:30:31 meet2 launch.sh[6121]: Aug 13, 2020 9:30:31 PM org.jitsi.jibri.api.xmpp.XmppApi handleJibriIq
Aug 13 21:30:31 meet2 launch.sh[6121]: INFO: Received JibriIq <iq to='focus@auth.meet2.opensuse.org/QCHwiOIt' from='jibribrewery@internal.auth.meet2.opensuse.org/focus' id='Zm9jdXNAYXV0aC5tZWV0Mi5vcGVuc3VzZS5vcmcvUUNId2lPSXQASVBQTlctOTU4ACZ8g5CBryA1WQTqQFBi+Sw=' type='set'><jibri xmlns='http://jitsi.org/protocol/jibri' action='stop'/></iq> from environment [MucClient id=meet2.opensuse.org hostname=meet2.opensuse.org]
Aug 13 21:30:31 meet2 launch.sh[6121]: Aug 13, 2020 9:30:31 PM org.jitsi.jibri.JibriManager stopService
Aug 13 21:30:31 meet2 launch.sh[6121]: INFO: Stopping the current service
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi handleJibriIq
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Received JibriIq <iq to='focus@auth.meet2.opensuse.org/QCHwiOIt' from='jibribrewery@internal.auth.meet2.opensuse.org/focus' id='Zm9jdXNAYXV0aC5tZWV0Mi5vcGVuc3VzZS5vcmcvUUNId2lPSXQASVBQTlctOTgyACZ8g5CBryA1WQTqQFBi+Sw=' type='set'><jibri xmlns='http://jitsi.org/protocol/jibri' action='start' recording_mode='file' room='desperatepenguinsfinishruthlessly@conference.meet2.opensuse.org' session_id='bzxciempjgioizwl' app_data='{"file_recording_metadata":{"share":true}}'/></iq> from environment [MucClient id=meet2.opensuse.org hostname=meet2.opensuse.org]
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi handleStartJibriIq
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Received start request
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi handleStartJibriIq
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Sending 'pending' response to start IQ
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi$handleStartJibriIq$1 run
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Starting service
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi handleStartService
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Parsed call url info: CallUrlInfo(baseUrl=https://meet2.opensuse.org, callName=desperatepenguinsfinishruthlessly, urlParams=[])
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.JibriManager startFileRecording
Aug 13 21:30:42 meet2 launch.sh[6121]: INFO: Starting a file recording with params: FileRecordingRequestParams(callParams=CallParams(callUrlInfo=CallUrlInfo(baseUrl=https://meet2.opensuse.org, callName=desperatepenguinsfinishruthlessly, urlParams=[])), sessionId=bzxciempjgioizwl, callLoginParams=XmppCredentials(domain=recorder.meet2.opensuse.org, username=recorder, password=YOURSECRET3)) finalize script path: /usr/share/jitsi-jibri/finalize_recording.sh and recordings directory: /srv/recordings
Aug 13 21:30:42 meet2 launch.sh[6121]: Aug 13, 2020 9:30:42 PM org.jitsi.jibri.api.xmpp.XmppApi$handleStartJibriIq$1 run
Aug 13 21:30:42 meet2 launch.sh[6121]: SEVERE: Error starting Jibri service : java.lang.NoClassDefFoundError: Could not initialize class org.jitsi.jibri.selenium.JibriSelenium with stack:
Aug 13 21:30:42 meet2 launch.sh[6121]: org.jitsi.jibri.service.impl.FileRecordingJibriService.<init>(FileRecordingJibriService.kt:105)
Aug 13 21:30:42 meet2 launch.sh[6121]: org.jitsi.jibri.JibriManager.startFileRecording(JibriManager.kt:134)
Aug 13 21:30:42 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi.handleStartService(XmppApi.kt:281)
Aug 13 21:30:42 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi.access$handleStartService(XmppApi.kt:67)
Aug 13 21:30:42 meet2 launch.sh[6121]: org.jitsi.jibri.api.xmpp.XmppApi$handleStartJibriIq$1.run(XmppApi.kt:191)
Aug 13 21:30:42 meet2 launch.sh[6121]: java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
Aug 13 21:30:42 meet2 launch.sh[6121]: java.util.concurrent.FutureTask.run(FutureTask.java:266)
Aug 13 21:30:42 meet2 launch.sh[6121]: java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
Aug 13 21:30:42 meet2 launch.sh[6121]: java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
Aug 13 21:30:42 meet2 launch.sh[6121]: java.lang.Thread.run(Thread.java:748)
Expected Behavior
Recording works.
Possible Solution
I saw in the forums a lot of issues around Selenium. The error reporting around this is vague and could be improved. Both stacktraces we got above are not telling us anything.
I also did put in the first line of init
in JibriSelenium
a Logger.info()
but this is not put out anywhere. Thus I guess we fail before reaching it.
My wild guess is that this is caused by the follwing line: private val stateMachine = SeleniumStateMachine()
Also to verify that this is working I put in for Selenium the following Java System Property: -Dwebdriver.chrome.driver="/usr/local/bin/chromedriver"
it made no difference, the stacktrace stays the same.
When monitoring with htop I can see that chrome is never starting up as well as I never see the Selenium Server being started.
Steps to reproduce
We followed the install guide in the README. I was able to reproduce this both with Java 1.8 and the Jibri Tag 8.0 (old config) and Java 11 on Git HEAD (new config).
Environment details
OS: openSUSE Leap 15.2
Java:
meet2:~/repos/jibri # java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (IcedTea 3.16.0) (build 1.8.0_252-b09 suse-lp152.1.2-x86_64)
OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)
meet2:~/repos/jibri # javac -version
javac 1.8.0_252
Процесс установки и настройки сервиса видеоконференций Jitsi Meet был описан в одной из предыдущих заметок.
Указанная в той заметке конфигурация срвиса была лишена одной немаловажной возможности, а именно возможности вести видеозапись конференции.
За наличие этой возможности отвечает сервис Jibri (JItsi BRoadcasting Infrastructure). Его настройка и будет описана далее.
Специфика работы Jibri такова, что один экземпляр этой службы может записывать только одну конференцию. Это происходит из-за того, что при нажатии
кнопки «Начать запись» Jibri подключается к конференции как участник и после этого записывает видео. Чтобы решить эту проблему и не плодить
при этом серверы с Jibri будем использовать docker-контейнеры.
Напомню, что Jitsi Meet установлен на Ubuntu 18.04 с адресом meet.oldfag.ru. На этот же сервер установим Docker Comunity Edition, где и будем запускать контейнеры с Jibri, чтобы ресурсы сервера не простаивали.
Однако если запускать контейнеры на другой машине, то в последовательности действий абсолютно ничего не изменится.
Описание настройки, для удобства, разделю на следующие этапы:
— настройка Prosody
— настройка Jicofo
— настройка интерфейса Jitsi Meet
— настройка ОС, на которой установлен Jitsi Meet
— установка docker, запуск и настройка сервиса Jibri
Так как подходящего способа получить количество активных комнат на сервере я так и не нашёл, плагин для Prosody mod_muc_size мне победить не удалось,
а так же не нашлось способа контролировать проставивают ли сейчас экземпляры Jibri в контейнерах и останавливать таковые, то просто буду запускать 5
экземпляров службы, т.к. с вероятностью, близкой к 100%, на данном сервере не будет запущено более 5 видеоконференций одновременно.
Предполагается, что все команды выполняются от имени пользователя с повышенными полномочиями, например через
sudo -s
Инструкция по настройке служб Jitsi Meet для использования Jibri есть на GitHub Jitsi
Начнём с того, что настроим ядро всей системы — jabber-сервер Prosody.
Откроем файл конфигурации нашего сервера
nano /etc/prosody/conf.avail/meet.oldfag.ru.cfg.lua
и добавим ещё один виртуальный хост
VirtualHost "recorder.meet.oldfag.ru" modules_enabled = { "ping"; } authentication = "internal_plain"
а так же внесём изменения в уже существующую секцию
-- internal muc component Component "internal.auth.meet.oldfag.ru" "muc" storage = "none" modules_enabled = { "ping"; } admins = { "focus@auth.meet.oldfag.ru", "jvb@auth.meet.oldfag.ru" } muc_room_locking = false muc_room_default_public_jids = true muc_room_cache_size = 1000 <<==== вот эту строку добавляем
Создадим на Prosody двух локальных пользователей, одного для коммуникации с Jibri, отправки ему команд и получения его статуса — jibri,
второго для непосредственно подключения к конференциям и записи видео — recorder.
prosodyctl register jibri auth.meet.oldfag.ru jibri-auth-strong-pass prosodyctl register recorder recorder.meet.oldfag.ru jibri-recorder-strong-pass
Настройка закончена, перезапускаем службу для применения настроек.
systemctl restart prosody
Службу можно перезапустить так же и с использованием prosodyctl
prosodyctl restart
Переходим к настройке модератора конференций — Jicofo (JItsi COnference FOcus).
Откроем файл /etc/jitsi/jicofo/sip-communicator.properties и добавим строки
org.jitsi.jicofo.jibri.BREWERY=JibriBrewery@internal.auth.meet.oldfag.ru org.jitsi.jicofo.jibri.PENDING_TIMEOUT=90
Сохраним изменения и перезапустим службу
systemctl restart jicofo
В интерфейс Jitsi Meet нужно добавить кнопки для записи и трансляции видео, для этого открываем файл /etc/jitsi/meet/meet.oldfag.ru-config.js,
переходим в секцию Recording и меняем строки
на
fileRecordingsEnabled: true, liveStreamingEnabled: true,
а так же добавляем строку
hiddenDomain: 'recorder.meet.oldfag.ru',
Кроме изменения настроек сервисов, так же нужно добавить ALSA-loopback устройства в ОС, на которой запущен сервис Jitsi Meet.
Количество этих устройств должно быть не меньше количества экземпляров Jibri, которые планируется использовать. В данном случае их будет создано 5 штук.
Инструкция по их настройке есть на GitHub Jitsi.
Обновим установленные пакеты и установим дополнительные драйверы
apt update && apt upgrade -y apt install linux-image-extra-virtual -y
создадим 5 устройств для захвата
echo "options snd-aloop enable=1,1,1,1,1 index=0,1,2,3,4" > /etc/modprobe.d/alsa-loopback.conf
добавим загрузку модуля при старте системы
echo "snd-aloop" >> /etc/modules
и загрузим модуль ядра в текущем сеансе, без перезагрузки системы
modprobe snd_aloop
Проверим, что модуль загружен
lsmod | grep snd_aloop
Если всё хорошо, то ответ будет таким
snd_aloop 24576 0 snd_pcm 98304 1 snd_aloop snd 81920 3 snd_timer,snd_aloop,snd_pcm
А теперь последнее по очереди, но не по значению — насройка docker и запуск контейнеров Jibri.
Для начала установим docker согласно инструкции.
Добавим ключ безопасности репозитория
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
и сам репозиторий
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
Обновим список доступных пакетов и установим необходимые
apt update && apt install docker-ce docker-ce-cli containerd.io docker-compose -y
После того, как всё установится можно проверить что всё работает, запустив тестовый контейнер
docker run hello-world
Образ будет загружен из Docker Hub и запущен, если всё хорошо, то в консоли отобразится сообщение
Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
Не забываем добавить автозагрузку
systemctl enable docker
Создадим каталог хранения конфигурационных файлов для контейнеров
mkdir /etc/jibri-docker
а в нём файл конфигурации контейнера
touch /etc/jibri-docker/jibri.yml
со следующим содержанием
version: '3' services: jibri: image: jitsi/jibri volumes: - ${CONFIG}/jibri:/config - /dev/shm:/dev/shm cap_add: - SYS_ADMIN - NET_BIND_SERVICE devices: - /dev/snd:/dev/snd environment: - XMPP_AUTH_DOMAIN - XMPP_INTERNAL_MUC_DOMAIN - XMPP_RECORDER_DOMAIN - XMPP_SERVER - XMPP_DOMAIN - JIBRI_XMPP_USER - JIBRI_XMPP_PASSWORD - JIBRI_BREWERY_MUC - JIBRI_RECORDER_USER - JIBRI_RECORDER_PASSWORD - JIBRI_RECORDING_DIR - JIBRI_FINALIZE_RECORDING_SCRIPT_PATH - JIBRI_STRIP_DOMAIN_JID - JIBRI_LOGS_DIR - DISPLAY=:0 - TZ
В yml-файле не должно быть табуляций, все отступы создаются только пробелами.
Тут же создадим файл с переменными окружения
touch /etc/jibri-docker/.env
который будет содержать значения имён и паролей пользователей prosody, созданных ранее, адреса подключения и другие параметры.
XMPP_AUTH_DOMAIN=auth.meet.oldfag.ru XMPP_INTERNAL_MUC_DOMAIN=internal.auth.meet.oldfag.ru XMPP_RECORDER_DOMAIN=recorder.meet.oldfag.ru XMPP_SERVER=meet.oldfag.ru XMPP_DOMAIN=meet.oldfag.ru JIBRI_XMPP_USER=jibri JIBRI_XMPP_PASSWORD=jibri-auth-strong-pass JIBRI_BREWERY_MUC=jibribrewery JIBRI_RECORDER_USER=recorder JIBRI_RECORDER_PASSWORD=jibri-recorder-strong-pass JIBRI_RECORDING_DIR=/config/recordings JIBRI_FINALIZE_RECORDING_SCRIPT_PATH=/config/finalize.sh JIBRI_STRIP_DOMAIN_JID=conference JIBRI_LOGS_DIR=/config/logs DISPLAY=:0=
Пробуем запустить контейнер
cd /etc/jibri-docker docker-compose -f jibri.yml up
Если ufw активен, то тут можно будет увидеть ошибку
org.jivesoftware.smack.SmackException$ConnectionException: The following addresses failed: 'meet.oldfag.ru:5222' failed because: meet.oldfag.ru/192.168.1.147 exception: java.net.SocketTimeoutException: connect timed out
Останавливаем контейнер (Ctlr+C).
Добавляем правило для 5222 порта, это порт, используемый Jicofo
ufw allow 5222
Запускаем контейнер снова. Если всё хорошо, то в консоли можно будет увидеть
jibri_1 | 2020-10-22 09:48:44.648 INFO: [27] org.jitsi.xmpp.mucclient.MucClient.log() Joined MUC: jibribrewery@internal.auth.meet.oldfag.ru
Опять останавливаем контейнер и переходим к тому, что будет запущено 5 контейнеров, для одновременной записи 5 конференций. Если
нужно больше 5, то нужно не забыть кроме увеличения количества контейнеров увеличить количество ALSA-loopback устройств на сервере Jitsi.
Запустить несколько контейнеров сразу можно с помощью ключа —scale
docker-compose -f jibri.yml up --scale jibri=5 -d
jibri после ключа —scale в этой команде — имя службы, указанное в yml-файле, ключ -d нужен для того, чтобы контейнер запустился
без вывода всего и вся в консоль.
После этой команды будет запущено 5 контейнеров, но при этом на Jitsi будет доступна запись только одной конференции одновременно. Это происходит
из-за того, что для каждого экземпляра Jibri нужно указать своё ALSA-loopback устройство.
Чтобы это сделать выполним команды
docker exec jibridocker_jibri_1 sed -i 's/Loopback/0/g' /home/jibri/.asoundrc docker exec jibridocker_jibri_2 sed -i 's/Loopback/1/g' /home/jibri/.asoundrc docker exec jibridocker_jibri_3 sed -i 's/Loopback/2/g' /home/jibri/.asoundrc docker exec jibridocker_jibri_4 sed -i 's/Loopback/3/g' /home/jibri/.asoundrc docker exec jibridocker_jibri_5 sed -i 's/Loopback/4/g' /home/jibri/.asoundrc
и перезапустим контейнеры
docker restart jibridocker_jibri_1 jibridocker_jibri_2 jibridocker_jibri_3 jibridocker_jibri_4 jibridocker_jibri_5
Команды настройки устройств ALSA-loopback и перезапуска контейнеров лучше записать в отдельный исполняемый файл, т.к. они могут понадобится при
неосторожном удалении контейнеров или обновлении образа Jibri из Docker Hub.
Чтобы контейнеры поднимались при старте системы нужно выполнить команду
docker update --restart always <CONTAINER ID 1> <CONTAINER ID 2> ... <CONTAINER ID 5>
Идентификатор контейнера можно узнать выполнив команду
docker ps -a
Чтобы остановить контейнеры, если это необходимо, нужно использовать команду
docker-compose -f jibri.yml stop
а не
docker-compose -f jibri.yml down
т.к. последняя не только остановит контейнеры, но и удалит их, а следовательно и конфигурацию устройств в них.
Всё готово. Можно создать конференцию, открыть меню конференции, нажав на три точки в правом нижнем углу, выбрать пункт «Начать запись» и
услышать заветное: «Recording is on.»
Записи видеоконференций хранятся в /jibri/recordings/. Для постобработки записи (перемещение, публикация и т.д.) можно создать
скрипт /jibri/finalize.sh, его имя может быть любым, но оно должно быть указано в /etc/jibri-docker/.env в
параметре JIBRI_FINALIZE_RECORDING_SCRIPT_PATH. Его пример
можно найти на GitHub Jitsi
2020-04-18 19:06:12.543 SEVERE: [21] org.jitsi.xmpp.mucclient.MucClientManager.log() Failed to initialize and start a MucClient:
org.jivesoftware.smack.SmackException$ConnectionException: The following addresses failed: ‘osboxes.demoanuswadh.info:5222’ failed because: osboxes.demoanuswadh.info/77.525.75.82 exception: java.net.ConnectException: Connection refused (Connection refused)
В вашем журнале указано, что jibri подключается к osboxes.demoanuswadh.info (будет ли он разрешен для localhost или общедоступного IP-адреса?)
Если вы установили jitsi-meet и jibri на одном хосте, убедитесь, что osboxes.demoanuswadh.info должен быть разрешен как localhost.
Если вы установили на другой компьютер в одной подсети, osboxes.demoanuswadh.info должен быть преобразован в частный IP-адрес.
Если вы установили на другой компьютер в одной подсети, osboxes.demoanuswadh.info должен быть преобразован в общедоступный IP-адрес.
В последних двух случаях убедитесь, что ваша просодия прослушивает привязку порта 5222 к 0.0.0.0, также разрешите доступ к брандмауэру с помощью ufw (брандмауэр ubuntu)