New upstream version 21.0.2+dfsg1
This commit is contained in:
parent
1f1bbb3518
commit
baafb6325b
706 changed files with 49633 additions and 5044 deletions
|
|
@ -3,16 +3,19 @@ project(rtmp-services)
|
|||
include_directories(${OBS_JANSSON_INCLUDE_DIRS})
|
||||
|
||||
set(rtmp-services_SOURCES
|
||||
twitch.c
|
||||
rtmp-common.c
|
||||
rtmp-custom.c
|
||||
rtmp-services-main.c)
|
||||
|
||||
set(rtmp-services_HEADERS
|
||||
twitch.h
|
||||
rtmp-format-ver.h)
|
||||
|
||||
set(RTMP_SERVICES_URL
|
||||
"https://obsproject.com/obs2_update/rtmp-services"
|
||||
CACHE STRING "Default services package URL")
|
||||
option(CHECK_FOR_SERVICE_UPDATES "Checks for service updates" OFF)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/lookup-config.h.in"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Serveis de transmissió"
|
|||
CustomStreamingServer="Servidor de transmissió personalitzat"
|
||||
Service="Servei"
|
||||
Server="Servidor"
|
||||
Server.Auto="Automàtic (recomanat)"
|
||||
StreamKey="Clau de la transmissió"
|
||||
UseAuth="Usa autenticació"
|
||||
Username="Nom d’usuari"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Streamovací služby"
|
|||
CustomStreamingServer="Vlastní streamovací server"
|
||||
Service="Služba"
|
||||
Server="Server"
|
||||
Server.Auto="Automaticky (doporučeno)"
|
||||
StreamKey="Vysílací klíč"
|
||||
UseAuth="Použít ověření"
|
||||
Username="Uživatelské jméno"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Streaming Tjenester"
|
|||
CustomStreamingServer="Brugerdefineret Streaming Server"
|
||||
Service="Service"
|
||||
Server="Server"
|
||||
Server.Auto="Auto (anbefalet)"
|
||||
StreamKey="Stream nøgle"
|
||||
UseAuth="Brug godkendelse"
|
||||
Username="Brugernavn"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Streaming-Plattformen"
|
|||
CustomStreamingServer="Benutzerdefinierter Streamingserver"
|
||||
Service="Plattform"
|
||||
Server="Server"
|
||||
Server.Auto="Automatisch (empfohlen)"
|
||||
StreamKey="Streamschlüssel"
|
||||
UseAuth="Authentifizierung verwenden"
|
||||
Username="Benutzername"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Streaming Services"
|
|||
CustomStreamingServer="Custom Streaming Server"
|
||||
Service="Service"
|
||||
Server="Server"
|
||||
Server.Auto="Auto (Recommended)"
|
||||
StreamKey="Stream key"
|
||||
UseAuth="Use authentication"
|
||||
Username="Username"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Servicio de retransmisión"
|
|||
CustomStreamingServer="Personalizar el servidor de retransmisión"
|
||||
Service="Servicio"
|
||||
Server="Servidor"
|
||||
Server.Auto="Automático (Recomendado)"
|
||||
StreamKey="Clave de retransmisión"
|
||||
UseAuth="Usar la autentificación"
|
||||
Username="Nombre de usuario"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Transmisio zerbitzuak"
|
|||
CustomStreamingServer="Transmisio zerbitzari pertsonalizatua"
|
||||
Service="Zerbitzua"
|
||||
Server="Zerbitzaria"
|
||||
Server.Auto="Auto (gomendatua)"
|
||||
StreamKey="Transmisio giltza"
|
||||
UseAuth="Erabili autentifikazioa"
|
||||
Username="Erabiltzaile-izena"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Palvelut"
|
|||
CustomStreamingServer="Valinnainen palvelin"
|
||||
Service="Palvelu"
|
||||
Server="Palvelin"
|
||||
Server.Auto="Automaattinen (suositus)"
|
||||
StreamKey="Striimiavain"
|
||||
UseAuth="Käytä todennusta"
|
||||
Username="Käyttäjätunnus"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Services de streaming"
|
|||
CustomStreamingServer="Serveur de streaming personnalisé"
|
||||
Service="Service"
|
||||
Server="Serveur"
|
||||
Server.Auto="Auto (Recommandé)"
|
||||
StreamKey="Clé de stream"
|
||||
UseAuth="Utiliser l'authentification"
|
||||
Username="Nom d'utilisateur"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Stream kiszolgáló"
|
|||
CustomStreamingServer="Egyéni stream szerver"
|
||||
Service="Szolgáltatás"
|
||||
Server="Szerver"
|
||||
Server.Auto="Automatikus (Ajánlott)"
|
||||
StreamKey="Stream kulcs"
|
||||
UseAuth="Hitelesítés használata"
|
||||
Username="Felhasználó"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Servizi di streaming"
|
|||
CustomStreamingServer="Personalizza il server di streaming"
|
||||
Service="Servizio"
|
||||
Server="Server"
|
||||
Server.Auto="Auto (consigliato)"
|
||||
StreamKey="Chiave Stream"
|
||||
UseAuth="Usa autenticazione"
|
||||
Username="Username"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="ストリーミングサービス"
|
|||
CustomStreamingServer="カスタムストリーミングサーバー"
|
||||
Service="サービス"
|
||||
Server="サーバー"
|
||||
Server.Auto="自動 (推奨)"
|
||||
StreamKey="ストリームキー"
|
||||
UseAuth="認証を使用する"
|
||||
Username="ユーザー名"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="방송 서비스"
|
|||
CustomStreamingServer="사용자 임의 방송 서버"
|
||||
Service="서비스"
|
||||
Server="서버"
|
||||
Server.Auto="자동 (권장)"
|
||||
StreamKey="스트림 키"
|
||||
UseAuth="접속 시 인증 필요"
|
||||
Username="사용자 이름"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Strømmingstjenester"
|
|||
CustomStreamingServer="Egendefinert strømmingserver"
|
||||
Service="Tjeneste"
|
||||
Server="Tjener"
|
||||
Server.Auto="Auto (Anbefales)"
|
||||
StreamKey="Strømingsnøkkel"
|
||||
UseAuth="Bruk godkjenning"
|
||||
Username="Brukernavn"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Streaming Diensten"
|
|||
CustomStreamingServer="Aangepaste Streaming Server"
|
||||
Service="Dienst"
|
||||
Server="Server"
|
||||
Server.Auto="Automatisch (aanbevolen)"
|
||||
StreamKey="Stream key"
|
||||
UseAuth="Gebruik authenticatie"
|
||||
Username="Gebruikersnaam"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Serwisy strumieniowania"
|
|||
CustomStreamingServer="Własny serwer strumieniowania"
|
||||
Service="Serwis"
|
||||
Server="Serwer"
|
||||
Server.Auto="Automatycznie (zalecane)"
|
||||
StreamKey="Klucz strumienia"
|
||||
UseAuth="Użyj uwierzytelniania"
|
||||
Username="Użytkownik"
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ StreamingServices="Serviços de Streaming"
|
|||
CustomStreamingServer="Servidor de Streaming Personalizado"
|
||||
Service="Serviço"
|
||||
Server="Servidor"
|
||||
Server.Auto="Automático (recomendado)"
|
||||
StreamKey="Chave da Stream"
|
||||
UseAuth="Utilizar autenticação"
|
||||
Username="Usuario"
|
||||
Username="Usuário"
|
||||
Password="Senha"
|
||||
ShowAll="Mostrar todos os serviços"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Сервисы вещания"
|
|||
CustomStreamingServer="Пользовательский сервер вещания"
|
||||
Service="Сервис"
|
||||
Server="Сервер"
|
||||
Server.Auto="Автоматически (Рекомендуется)"
|
||||
StreamKey="Ключ потока"
|
||||
UseAuth="Использовать авторизацию"
|
||||
Username="Имя пользователя"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Streamovacie služby"
|
|||
CustomStreamingServer="Vlastný stream server"
|
||||
Service="Služba"
|
||||
Server="Server"
|
||||
Server.Auto="Automaticky (odporúča sa)"
|
||||
StreamKey="Stream kľúč"
|
||||
UseAuth="Použiť overenie"
|
||||
Username="Užívateľské meno"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Strömtjänster"
|
|||
CustomStreamingServer="Anpassad streamningsserver"
|
||||
Service="Tjänst"
|
||||
Server="Server"
|
||||
Server.Auto="Auto (rekommenderad)"
|
||||
StreamKey="Streamnyckel"
|
||||
UseAuth="Använd autentisering"
|
||||
Username="Användarnamn"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Yayın Servisleri"
|
|||
CustomStreamingServer="Özel Yayın Sunucusu"
|
||||
Service="Servis"
|
||||
Server="Sunucu"
|
||||
Server.Auto="Otomatik (Önerilen)"
|
||||
StreamKey="Yayın Anahtarı"
|
||||
UseAuth="Kimlik doğrulaması kullan"
|
||||
Username="Kullanıcı Adı"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="Сервіси трансляцій"
|
|||
CustomStreamingServer="Сервер користувача"
|
||||
Service="Сервіс"
|
||||
Server="Сервер"
|
||||
Server.Auto="Автоматично (рекомендується)"
|
||||
StreamKey="Ключ трансляції"
|
||||
UseAuth="Використовувати авторизацію"
|
||||
Username="Логін"
|
||||
|
|
|
|||
11
plugins/rtmp-services/data/locale/vi-VN.ini
Normal file
11
plugins/rtmp-services/data/locale/vi-VN.ini
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
StreamingServices="Dịch vụ stream"
|
||||
CustomStreamingServer="Tùy chọn máy chủ truyền trực tuyến"
|
||||
Service="Dịch vụ"
|
||||
Server="Máy chủ"
|
||||
Server.Auto="Âm thanh (Khuyến nghị)"
|
||||
StreamKey="Khóa stream"
|
||||
UseAuth="Xác thực sử dụng"
|
||||
Username="Tài khoản"
|
||||
Password="Mật khẩu"
|
||||
ShowAll="Hiển tất cả các dịch vụ"
|
||||
|
||||
|
|
@ -2,6 +2,7 @@ StreamingServices="流媒体服务"
|
|||
CustomStreamingServer="自定义流媒体服务器"
|
||||
Service="服务"
|
||||
Server="服务器"
|
||||
Server.Auto="自动(推荐)"
|
||||
StreamKey="流名称"
|
||||
UseAuth="使用身份验证"
|
||||
Username="用户名"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ StreamingServices="串流服務"
|
|||
CustomStreamingServer="自訂串流伺服器"
|
||||
Service="服務商"
|
||||
Server="伺服器"
|
||||
Server.Auto="自動 (建議)"
|
||||
StreamKey="串流金鑰"
|
||||
UseAuth="使用身份驗證"
|
||||
Username="使用者名稱"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"url": "https://obsproject.com/obs2_update/rtmp-services",
|
||||
"version": 60,
|
||||
"version": 77,
|
||||
"files": [
|
||||
{
|
||||
"name": "services.json",
|
||||
"version": 60
|
||||
"version": 77
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,6 @@
|
|||
"name": "Twitch",
|
||||
"common": true,
|
||||
"servers": [
|
||||
{
|
||||
"name": "US West: San Francisco, CA",
|
||||
"url": "rtmp://live.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "Asia: Hong Kong",
|
||||
"url": "rtmp://live-hkg.twitch.tv/app"
|
||||
|
|
@ -37,10 +33,18 @@
|
|||
"name": "EU: Amsterdam, NL",
|
||||
"url": "rtmp://live-ams.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "EU: Berlin, DE",
|
||||
"url": "rtmp://live-ber.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "EU: Frankfurt, DE",
|
||||
"url": "rtmp://live-fra.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "EU: Helsinki, FI",
|
||||
"url": "rtmp://live-hel.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "EU: Lisbon, Portugal",
|
||||
"url": "rtmp://live-lis.twitch.tv/app"
|
||||
|
|
@ -53,6 +57,10 @@
|
|||
"name": "EU: Madrid, Spain",
|
||||
"url": "rtmp://live-mad.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "EU: Marseille, FR",
|
||||
"url": "rtmp://live-mrs.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "EU: Milan, Italy",
|
||||
"url": "rtmp://live-mil.twitch.tv/app"
|
||||
|
|
@ -81,6 +89,10 @@
|
|||
"name": "NA: Mexico City",
|
||||
"url": "rtmp://live-qro.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "NA: Quebec, Canada",
|
||||
"url": "rtmp://live-ymq.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "NA: Toronto, Canada",
|
||||
"url": "rtmp://live-yto.twitch.tv/app"
|
||||
|
|
@ -98,7 +110,7 @@
|
|||
"url": "rtmp://live-lim.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "South America: Medellin, Columbia",
|
||||
"name": "South America: Medellin, Colombia",
|
||||
"url": "rtmp://live-mde.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
|
|
@ -121,6 +133,10 @@
|
|||
"name": "US Central: Houston, TX",
|
||||
"url": "rtmp://live-hou.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "US Central: Salt Lake City, UT",
|
||||
"url": "rtmp://live-slc.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "US East: Ashburn, VA",
|
||||
"url": "rtmp://live-iad.twitch.tv/app"
|
||||
|
|
@ -149,6 +165,14 @@
|
|||
"name": "US West: Phoenix, AZ",
|
||||
"url": "rtmp://live-phx.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "US West: Portland, Oregon",
|
||||
"url": "rtmp://live-pdx.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "US West: San Francisco, CA",
|
||||
"url": "rtmp://live-sfo.twitch.tv/app"
|
||||
},
|
||||
{
|
||||
"name": "US West: San Jose, CA",
|
||||
"url": "rtmp://live-sjc.twitch.tv/app"
|
||||
|
|
@ -273,93 +297,198 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "beam.pro",
|
||||
"name": "Mixer.com - FTL",
|
||||
"common": true,
|
||||
"servers": [
|
||||
{
|
||||
"name": "US: Dallas, TX",
|
||||
"url": "rtmp://ingest-dal.beam.pro:1935/beam"
|
||||
"url": "ingest-dal.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "US: San Jose, CA",
|
||||
"url": "rtmp://ingest-sjc.beam.pro:1935/beam"
|
||||
"url": "ingest-sjc.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "US: Seattle, WA",
|
||||
"url": "rtmp://ingest-sea.beam.pro:1935/beam"
|
||||
"url": "ingest-sea.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "US: Washington DC",
|
||||
"url": "rtmp://ingest-wdc.beam.pro:1935/beam"
|
||||
"url": "ingest-wdc.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "Canada: Toronto",
|
||||
"url": "rtmp://ingest-tor.beam.pro:1935/beam"
|
||||
"url": "ingest-tor.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "EU: London",
|
||||
"url": "rtmp://ingest-lon.beam.pro:1935/beam"
|
||||
"url": "ingest-lon.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "EU: Amsterdam",
|
||||
"url": "rtmp://ingest-ams.beam.pro:1935/beam"
|
||||
"url": "ingest-ams.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "EU: Milan",
|
||||
"url": "rtmp://ingest-mil.beam.pro:1935/beam"
|
||||
"url": "ingest-mil.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "EU: Paris",
|
||||
"url": "rtmp://ingest-par.beam.pro:1935/beam"
|
||||
"url": "ingest-par.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "EU: Frankfurt",
|
||||
"url": "rtmp://ingest-fra.beam.pro:1935/beam"
|
||||
"url": "ingest-fra.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "EU: Oslo",
|
||||
"url": "rtmp://ingest-osl.beam.pro:1935/beam"
|
||||
"url": "ingest-osl.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "Brazil: Sao Paulo",
|
||||
"url": "rtmp://ingest-sao.beam.pro:1935/beam"
|
||||
"url": "ingest-sao.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "Australia: Melbourne",
|
||||
"url": "rtmp://ingest-mel.beam.pro:1935/beam"
|
||||
"url": "ingest-mel.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "Australia: Sydney",
|
||||
"url": "rtmp://ingest-syd.beam.pro:1935/beam"
|
||||
"url": "ingest-syd.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "Mexico: Mexico City",
|
||||
"url": "rtmp://ingest-mex.beam.pro:1935/beam"
|
||||
"url": "ingest-mex.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "Asia: Hong Kong",
|
||||
"url": "rtmp://ingest-hkg.beam.pro:1935/beam"
|
||||
"url": "ingest-hkg.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "Asia: Tokyo",
|
||||
"url": "rtmp://ingest-tok.beam.pro:1935/beam"
|
||||
"url": "ingest-tok.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "South Korea: Seoul",
|
||||
"url": "rtmp://ingest-seo.beam.pro:1935/beam"
|
||||
"url": "ingest-seo.mixer.com"
|
||||
},
|
||||
{
|
||||
"name": "India: Chennai",
|
||||
"url": "rtmp://ingest-che.beam.pro:1935/beam"
|
||||
"url": "ingest-che.mixer.com"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 1,
|
||||
"keyint": 3,
|
||||
"output": "ftl_output",
|
||||
"max audio bitrate": 160,
|
||||
"max video bitrate": 10000,
|
||||
"profile": "main",
|
||||
"bframes": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Mixer.com - RTMP",
|
||||
"common": true,
|
||||
"servers": [
|
||||
{
|
||||
"name": "US: Dallas, TX",
|
||||
"url": "rtmp://ingest-dal.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "US: San Jose, CA",
|
||||
"url": "rtmp://ingest-sjc.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "US: Seattle, WA",
|
||||
"url": "rtmp://ingest-sea.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "US: Washington DC",
|
||||
"url": "rtmp://ingest-wdc.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "Canada: Toronto",
|
||||
"url": "rtmp://ingest-tor.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "EU: London",
|
||||
"url": "rtmp://ingest-lon.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "EU: Amsterdam",
|
||||
"url": "rtmp://ingest-ams.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "EU: Milan",
|
||||
"url": "rtmp://ingest-mil.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "EU: Paris",
|
||||
"url": "rtmp://ingest-par.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "EU: Frankfurt",
|
||||
"url": "rtmp://ingest-fra.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "EU: Oslo",
|
||||
"url": "rtmp://ingest-osl.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "Brazil: Sao Paulo",
|
||||
"url": "rtmp://ingest-sao.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "Australia: Melbourne",
|
||||
"url": "rtmp://ingest-mel.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "Australia: Sydney",
|
||||
"url": "rtmp://ingest-syd.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "Mexico: Mexico City",
|
||||
"url": "rtmp://ingest-mex.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "Asia: Hong Kong",
|
||||
"url": "rtmp://ingest-hkg.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "Asia: Tokyo",
|
||||
"url": "rtmp://ingest-tok.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "South Korea: Seoul",
|
||||
"url": "rtmp://ingest-seo.mixer.com:1935/beam"
|
||||
},
|
||||
{
|
||||
"name": "India: Chennai",
|
||||
"url": "rtmp://ingest-che.mixer.com:1935/beam"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 3,
|
||||
"max audio bitrate": 160,
|
||||
"max video bitrate": 10000,
|
||||
"profile": "main"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Mobcrush",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Primary",
|
||||
"url": "rtmp://live.mobcrush.net/mob"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"profile": "main",
|
||||
"max video bitrate": 6000,
|
||||
"max audio bitrate": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "DailyMotion",
|
||||
"common": true,
|
||||
|
|
@ -394,51 +523,6 @@
|
|||
"max audio bitrate": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Switchboard Live (Joicaster)",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Default - Performance Global",
|
||||
"url": "rtmp://ingest-global-a.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "U.S. - Dallas, TX",
|
||||
"url": "rtmp://ingest-us-dal.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "U.S. - Seattle, WA",
|
||||
"url": "rtmp://ingest-us-sea.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "U.S. - Washington, DC",
|
||||
"url": "rtmp://ingest-us-wdc.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "C.A. - Toronto, Canada",
|
||||
"url": "rtmp://ingest-cn-tor.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "E.U. - London, England",
|
||||
"url": "rtmp://ingest-eu-lon.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "E.U. - Amsterdam, Netherlands",
|
||||
"url": "rtmp://ingest-as-tok.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "A.S. - Tokyo, Japan",
|
||||
"url": "rtmp://ingest-as-tok.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "A.U. - Melbourne, Australia",
|
||||
"url": "rtmp://ingest-au-mel.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "S.A - São Paulo, Brazil",
|
||||
"url": "rtmp://ingest-sa-sao.switchboard.zone/live"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "GoodGame.ru",
|
||||
"servers": [
|
||||
|
|
@ -473,8 +557,8 @@
|
|||
"url": "rtmp://live-den.vaughnsoft.net/live"
|
||||
},
|
||||
{
|
||||
"name": "US: Los Angeles, CA",
|
||||
"url": "rtmp://live-lax.vaughnsoft.net/live"
|
||||
"name": "US: New York, NY",
|
||||
"url": "rtmp://live-nyc.vaughnsoft.net/live"
|
||||
},
|
||||
{
|
||||
"name": "EU: Amsterdam, NL",
|
||||
|
|
@ -503,8 +587,8 @@
|
|||
"url": "rtmp://live-den.vaughnsoft.net/live"
|
||||
},
|
||||
{
|
||||
"name": "US: Los Angeles, CA",
|
||||
"url": "rtmp://live-lax.vaughnsoft.net/live"
|
||||
"name": "US: New York, NY",
|
||||
"url": "rtmp://live-nyc.vaughnsoft.net/live"
|
||||
},
|
||||
{
|
||||
"name": "EU: Amsterdam, NL",
|
||||
|
|
@ -573,6 +657,10 @@
|
|||
"name": "EU-West (Amsterdam, NL)",
|
||||
"url": "rtmp://eu-ams.restream.io/live"
|
||||
},
|
||||
{
|
||||
"name": "EU-West (Luxembourg)",
|
||||
"url": "rtmp://eu-luxembourg.restream.io/live"
|
||||
},
|
||||
{
|
||||
"name": "EU-Central (Frankfurt, DE)",
|
||||
"url": "rtmp://eu-central.restream.io/live"
|
||||
|
|
@ -581,6 +669,10 @@
|
|||
"name": "EU-East (Falkenstein, DE)",
|
||||
"url": "rtmp://eu-east.restream.io/live"
|
||||
},
|
||||
{
|
||||
"name": "EU-South (Madrid, Spain)",
|
||||
"url": "rtmp://eu-madrid.restream.io/live"
|
||||
},
|
||||
{
|
||||
"name": "Russia (Moscow)",
|
||||
"url": "rtmp://ru.restream.io/live"
|
||||
|
|
@ -601,6 +693,10 @@
|
|||
"name": "US-East (Washington, DC)",
|
||||
"url": "rtmp://us-east.restream.io/live"
|
||||
},
|
||||
{
|
||||
"name": "US-East (Miami, FL)",
|
||||
"url": "rtmp://us-miami.restream.io/live"
|
||||
},
|
||||
{
|
||||
"name": "NA-East (Toronto, Canada)",
|
||||
"url": "rtmp://na-toronto.restream.io/live"
|
||||
|
|
@ -689,18 +785,6 @@
|
|||
"max audio bitrate": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Coderwall",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Primary",
|
||||
"url": "rtmp://live.coderwall.com/coderwall"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"max video bitrate": 1500
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Meridix Live Sports Platform",
|
||||
"servers": [
|
||||
|
|
@ -812,15 +896,22 @@
|
|||
"name": "Picarto",
|
||||
"servers": [
|
||||
{
|
||||
"name": "USA/Canada",
|
||||
"url": "rtmp://live.us.picarto.tv/golive"
|
||||
"name": "US East (Chicago, USA)",
|
||||
"url": "rtmp://live.us-east1.picarto.tv/golive"
|
||||
},
|
||||
{
|
||||
"name": "US West (Los Angeles, USA)",
|
||||
"url": "rtmp://live.us-west1.picarto.tv/golive"
|
||||
},
|
||||
{
|
||||
"name": "EU West (Düsseldorf, Germany)",
|
||||
"url": "rtmp://live.eu-west1.picarto.tv/golive"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"profile": "main",
|
||||
"max video bitrate": 3500,
|
||||
"max audio bitrate": 128
|
||||
"max video bitrate": 3500
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -833,13 +924,244 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"name": "LiveStream",
|
||||
"name": "Livestream",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Primary",
|
||||
"url": "rtmp://rtmpin.livestreamingest.com/rtmpin"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Chaturbate",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Default Global Auto Select - Recommended",
|
||||
"url": "rtmp://live.stream.highwebmedia.com/live-origin"
|
||||
},
|
||||
{
|
||||
"name": "US West",
|
||||
"url": "rtmp://live-us-west.stream.highwebmedia.com/live-origin"
|
||||
},
|
||||
{
|
||||
"name": "US Central",
|
||||
"url": "rtmp://live-us-central.stream.highwebmedia.com/live-origin"
|
||||
},
|
||||
{
|
||||
"name": "US East",
|
||||
"url": "rtmp://live-us-east.stream.highwebmedia.com/live-origin"
|
||||
},
|
||||
{
|
||||
"name": "Europe West",
|
||||
"url": "rtmp://live-eu-west.stream.highwebmedia.com/live-origin"
|
||||
},
|
||||
{
|
||||
"name": "Europe East",
|
||||
"url": "rtmp://live-eu-east.stream.highwebmedia.com/live-origin"
|
||||
},
|
||||
{
|
||||
"name": "Asia/Pacific South",
|
||||
"url": "rtmp://live-as-south.stream.highwebmedia.com/live-origin"
|
||||
},
|
||||
{
|
||||
"name": "Asia/Pacific North-East",
|
||||
"url": "rtmp://live-as-northeast.stream.highwebmedia.com/live-origin"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"max video bitrate": 20000,
|
||||
"max audio bitrate": 192
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "LiveEdu.tv",
|
||||
"common": true,
|
||||
"servers": [
|
||||
{
|
||||
"name": "US",
|
||||
"url": "rtmp://usmedia11.liveedu.tv/liveedutv"
|
||||
},
|
||||
{
|
||||
"name": "EU",
|
||||
"url": "rtmp://eumedia8.liveedu.tv/liveedutv"
|
||||
},
|
||||
{
|
||||
"name": "Asia",
|
||||
"url": "rtmp://apmedia1.liveedu.tv/liveedutv"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Twitter / Periscope",
|
||||
"common": true,
|
||||
"servers": [
|
||||
{
|
||||
"name": "US West: California",
|
||||
"url": "rtmp://ca.pscp.tv:80/x"
|
||||
},
|
||||
{
|
||||
"name": "US West: Oregon",
|
||||
"url": "rtmp://or.pscp.tv:80/x"
|
||||
},
|
||||
{
|
||||
"name": "US East: Virginia",
|
||||
"url": "rtmp://va.pscp.tv:80/x"
|
||||
},
|
||||
{
|
||||
"name": "South America: Brazil",
|
||||
"url": "rtmp://br.pscp.tv:80/x"
|
||||
},
|
||||
{
|
||||
"name": "EU West: Ireland",
|
||||
"url": "rtmp://ie.pscp.tv:80/x"
|
||||
},
|
||||
{
|
||||
"name": "EU Central: Germany",
|
||||
"url": "rtmp://de.pscp.tv:80/x"
|
||||
},
|
||||
{
|
||||
"name": "Asia/Pacific: Australia",
|
||||
"url": "rtmp://au.pscp.tv:80/x"
|
||||
},
|
||||
{
|
||||
"name": "Asia/Pacific: Japan",
|
||||
"url": "rtmp://jp.pscp.tv:80/x"
|
||||
},
|
||||
{
|
||||
"name": "Asia/Pacific: Singapore",
|
||||
"url": "rtmp://sg.pscp.tv:80/x"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"max video bitrate": 800,
|
||||
"max audio bitrate": 96
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Switchboard Live (Joicaster)",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Default - Performance Global",
|
||||
"url": "rtmp://ingest-global-a.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "US West",
|
||||
"url": "rtmp://ingest-us-west.a.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "US East",
|
||||
"url": "rtmp://ingest-us-east.a.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "Europe West",
|
||||
"url": "rtmp://ingest-eu-west.a.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "Europe Central",
|
||||
"url": "rtmp://ingest-us-east.a.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "Australia East",
|
||||
"url": "rtmp://ingest-au-east.a.switchboard.zone/live"
|
||||
},
|
||||
{
|
||||
"name": "Asia Central",
|
||||
"url": "rtmp://ingest-as-central.a.switchboard.zone/live"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Looch",
|
||||
"common": false,
|
||||
"servers": [
|
||||
{
|
||||
"name": "Primary Looch ingest server",
|
||||
"url": "rtmp://ingest.looch.tv/live"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"profile": "main",
|
||||
"max video bitrate": 6000,
|
||||
"max audio bitrate": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Stream.me",
|
||||
"common": false,
|
||||
"servers": [
|
||||
{
|
||||
"name": "US, Central",
|
||||
"url": "rtmp://uc-origin.stream.me/origin"
|
||||
},
|
||||
{
|
||||
"name": "US, East",
|
||||
"url": "rtmp://ue-origin.stream.me/origin"
|
||||
},
|
||||
{
|
||||
"name": "US, West",
|
||||
"url": "rtmp://uw-origin.stream.me/origin"
|
||||
},
|
||||
{
|
||||
"name": "Europe, West",
|
||||
"url": "rtmp://ew-origin.stream.me/origin"
|
||||
},
|
||||
{
|
||||
"name": "Asia, East",
|
||||
"url": "rtmp://ae-origin.stream.me/origin"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"profile": "main",
|
||||
"max video bitrate": 20000,
|
||||
"max audio bitrate": 192
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Eventials",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Default",
|
||||
"url": "rtmp://live.eventials.com/eventialsLiveOrigin"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 1,
|
||||
"profile": "baseline",
|
||||
"max video bitrate": 900,
|
||||
"max audio bitrate": 192
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Lahzenegar - لحظه نگار",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Primary",
|
||||
"url": "rtmp://live.lahzenegar.com:80/pro"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"max video bitrate": 1000,
|
||||
"max audio bitrate": 96
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "MyLive",
|
||||
"servers": [
|
||||
{
|
||||
"name": "Default",
|
||||
"url": "rtmp://stream.mylive.in.th/live"
|
||||
}
|
||||
],
|
||||
"recommended": {
|
||||
"keyint": 2,
|
||||
"profile": "main",
|
||||
"max video bitrate": 7000,
|
||||
"max audio bitrate": 192
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef ON
|
||||
#define ON 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef OFF
|
||||
#define OFF 0
|
||||
#endif
|
||||
|
||||
#define RTMP_SERVICES_URL "@RTMP_SERVICES_URL@"
|
||||
#define CHECK_FOR_SERVICE_UPDATES @CHECK_FOR_SERVICE_UPDATES@
|
||||
|
|
|
|||
|
|
@ -4,11 +4,14 @@
|
|||
#include <jansson.h>
|
||||
|
||||
#include "rtmp-format-ver.h"
|
||||
#include "twitch.h"
|
||||
|
||||
struct rtmp_common {
|
||||
char *service;
|
||||
char *server;
|
||||
char *key;
|
||||
|
||||
char *output;
|
||||
};
|
||||
|
||||
static const char *rtmp_common_getname(void *unused)
|
||||
|
|
@ -17,17 +20,42 @@ static const char *rtmp_common_getname(void *unused)
|
|||
return obs_module_text("StreamingServices");
|
||||
}
|
||||
|
||||
static json_t *open_services_file(void);
|
||||
static inline json_t *find_service(json_t *root, const char *name);
|
||||
static inline const char *get_string_val(json_t *service, const char *key);
|
||||
|
||||
extern void twitch_ingests_refresh(int seconds);
|
||||
|
||||
static void rtmp_common_update(void *data, obs_data_t *settings)
|
||||
{
|
||||
struct rtmp_common *service = data;
|
||||
|
||||
bfree(service->service);
|
||||
bfree(service->server);
|
||||
bfree(service->output);
|
||||
bfree(service->key);
|
||||
|
||||
service->service = bstrdup(obs_data_get_string(settings, "service"));
|
||||
service->server = bstrdup(obs_data_get_string(settings, "server"));
|
||||
service->key = bstrdup(obs_data_get_string(settings, "key"));
|
||||
service->output = NULL;
|
||||
|
||||
json_t *root = open_services_file();
|
||||
if (root) {
|
||||
json_t *serv = find_service(root, service->service);
|
||||
if (serv) {
|
||||
json_t *rec = json_object_get(serv, "recommended");
|
||||
if (rec && json_is_object(rec)) {
|
||||
const char *out = get_string_val(rec, "output");
|
||||
if (out)
|
||||
service->output = bstrdup(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
json_decref(root);
|
||||
|
||||
if (!service->output)
|
||||
service->output = bstrdup("rtmp_output");
|
||||
}
|
||||
|
||||
static void rtmp_common_destroy(void *data)
|
||||
|
|
@ -36,6 +64,7 @@ static void rtmp_common_destroy(void *data)
|
|||
|
||||
bfree(service->service);
|
||||
bfree(service->server);
|
||||
bfree(service->output);
|
||||
bfree(service->key);
|
||||
bfree(service);
|
||||
}
|
||||
|
|
@ -111,8 +140,6 @@ static void add_service(obs_property_t *list, json_t *service, bool show_all,
|
|||
obs_property_list_add_string(list, name, name);
|
||||
}
|
||||
|
||||
static inline json_t *find_service(json_t *root, const char *name);
|
||||
|
||||
static void add_services(obs_property_t *list, json_t *root, bool show_all,
|
||||
const char *cur_service)
|
||||
{
|
||||
|
|
@ -161,9 +188,9 @@ static json_t *open_json_file(const char *file)
|
|||
format_ver = get_int_val(root, "format_version");
|
||||
|
||||
if (format_ver != RTMP_SERVICES_FORMAT_VERSION) {
|
||||
blog(LOG_WARNING, "rtmp-common.c: [open_json_file] "
|
||||
"Wrong format version (%d), expected %d",
|
||||
format_ver, RTMP_SERVICES_FORMAT_VERSION);
|
||||
blog(LOG_DEBUG, "rtmp-common.c: [open_json_file] "
|
||||
"Wrong format version (%d), expected %d",
|
||||
format_ver, RTMP_SERVICES_FORMAT_VERSION);
|
||||
json_decref(root);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -218,6 +245,35 @@ static void properties_data_destroy(void *data)
|
|||
json_decref(root);
|
||||
}
|
||||
|
||||
static bool fill_twitch_servers_locked(obs_property_t *servers_prop)
|
||||
{
|
||||
size_t count = twitch_ingest_count();
|
||||
|
||||
obs_property_list_add_string(servers_prop,
|
||||
obs_module_text("Server.Auto"), "auto");
|
||||
|
||||
if (count <= 1)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
struct twitch_ingest ing = twitch_ingest(i);
|
||||
obs_property_list_add_string(servers_prop, ing.name, ing.url);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool fill_twitch_servers(obs_property_t *servers_prop)
|
||||
{
|
||||
bool success;
|
||||
|
||||
twitch_ingests_lock();
|
||||
success = fill_twitch_servers_locked(servers_prop);
|
||||
twitch_ingests_unlock();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void fill_servers(obs_property_t *servers_prop, json_t *service,
|
||||
const char *name)
|
||||
{
|
||||
|
|
@ -235,6 +291,15 @@ static void fill_servers(obs_property_t *servers_prop, json_t *service,
|
|||
return;
|
||||
}
|
||||
|
||||
if (strcmp(name, "Mixer.com - FTL") == 0) {
|
||||
obs_property_list_add_string(servers_prop,
|
||||
obs_module_text("Server.Auto"), "auto");
|
||||
}
|
||||
if (name && strcmp(name, "Twitch") == 0) {
|
||||
if (fill_twitch_servers(servers_prop))
|
||||
return;
|
||||
}
|
||||
|
||||
json_array_foreach (servers, index, server) {
|
||||
const char *server_name = get_string_val(server, "name");
|
||||
const char *url = get_string_val(server, "url");
|
||||
|
|
@ -363,6 +428,10 @@ static void apply_video_encoder_settings(obs_data_t *settings,
|
|||
}
|
||||
}
|
||||
|
||||
item = json_object_get(recommended, "bframes");
|
||||
if (item && json_is_integer(item))
|
||||
obs_data_set_int(settings, "bf", 0);
|
||||
|
||||
item = json_object_get(recommended, "x264opts");
|
||||
if (item && json_is_string(item)) {
|
||||
const char *x264_settings = json_string_value(item);
|
||||
|
|
@ -398,9 +467,10 @@ static void initialize_output(struct rtmp_common *service, json_t *root,
|
|||
json_t *recommended;
|
||||
|
||||
if (!json_service) {
|
||||
blog(LOG_WARNING, "rtmp-common.c: [initialize_output] "
|
||||
"Could not find service '%s'",
|
||||
service->service);
|
||||
if (service->service && *service->service)
|
||||
blog(LOG_WARNING, "rtmp-common.c: [initialize_output] "
|
||||
"Could not find service '%s'",
|
||||
service->service);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -427,9 +497,30 @@ static void rtmp_common_apply_settings(void *data,
|
|||
}
|
||||
}
|
||||
|
||||
static const char *rtmp_common_get_output_type(void *data)
|
||||
{
|
||||
struct rtmp_common *service = data;
|
||||
return service->output;
|
||||
}
|
||||
|
||||
static const char *rtmp_common_url(void *data)
|
||||
{
|
||||
struct rtmp_common *service = data;
|
||||
|
||||
if (service->service && strcmp(service->service, "Twitch") == 0) {
|
||||
if (service->server && strcmp(service->server, "auto") == 0) {
|
||||
struct twitch_ingest ing;
|
||||
|
||||
twitch_ingests_refresh(3);
|
||||
|
||||
twitch_ingests_lock();
|
||||
ing = twitch_ingest(0);
|
||||
twitch_ingests_unlock();
|
||||
|
||||
return ing.url;
|
||||
}
|
||||
}
|
||||
|
||||
return service->server;
|
||||
}
|
||||
|
||||
|
|
@ -449,4 +540,5 @@ struct obs_service_info rtmp_common_service = {
|
|||
.get_url = rtmp_common_url,
|
||||
.get_key = rtmp_common_key,
|
||||
.apply_encoder_settings = rtmp_common_apply_settings,
|
||||
.get_output_type = rtmp_common_get_output_type,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@ extern struct obs_service_info rtmp_common_service;
|
|||
extern struct obs_service_info rtmp_custom_service;
|
||||
|
||||
static update_info_t *update_info = NULL;
|
||||
static struct dstr module_name = {0};
|
||||
|
||||
const char *get_module_name(void)
|
||||
{
|
||||
return module_name.array;
|
||||
}
|
||||
|
||||
static bool confirm_service_file(void *param, struct file_download_data *file)
|
||||
{
|
||||
|
|
@ -40,23 +46,55 @@ static bool confirm_service_file(void *param, struct file_download_data *file)
|
|||
return true;
|
||||
}
|
||||
|
||||
extern void init_twitch_data(void);
|
||||
extern void load_twitch_data(void);
|
||||
extern void unload_twitch_data(void);
|
||||
extern void twitch_ingests_refresh(int seconds);
|
||||
|
||||
static void refresh_callback(void *unused, calldata_t *cd)
|
||||
{
|
||||
int seconds = (int)calldata_int(cd, "seconds");
|
||||
if (seconds <= 0)
|
||||
seconds = 3;
|
||||
if (seconds > 10)
|
||||
seconds = 10;
|
||||
|
||||
twitch_ingests_refresh(seconds);
|
||||
|
||||
UNUSED_PARAMETER(unused);
|
||||
}
|
||||
|
||||
bool obs_module_load(void)
|
||||
{
|
||||
init_twitch_data();
|
||||
|
||||
dstr_copy(&module_name, "rtmp-services plugin (libobs ");
|
||||
dstr_cat(&module_name, obs_get_version_string());
|
||||
dstr_cat(&module_name, ")");
|
||||
|
||||
proc_handler_t *ph = obs_get_proc_handler();
|
||||
proc_handler_add(ph, "void twitch_ingests_refresh(int seconds)",
|
||||
refresh_callback, NULL);
|
||||
|
||||
#if !defined(_WIN32) || CHECK_FOR_SERVICE_UPDATES
|
||||
char *local_dir = obs_module_file("");
|
||||
char *cache_dir = obs_module_config_path("");
|
||||
|
||||
if (cache_dir) {
|
||||
update_info = update_info_create(
|
||||
RTMP_SERVICES_LOG_STR,
|
||||
RTMP_SERVICES_VER_STR,
|
||||
module_name.array,
|
||||
RTMP_SERVICES_URL,
|
||||
local_dir,
|
||||
cache_dir,
|
||||
confirm_service_file, NULL);
|
||||
}
|
||||
|
||||
load_twitch_data();
|
||||
|
||||
bfree(local_dir);
|
||||
bfree(cache_dir);
|
||||
#endif
|
||||
|
||||
obs_register_service(&rtmp_common_service);
|
||||
obs_register_service(&rtmp_custom_service);
|
||||
|
|
@ -66,4 +104,6 @@ bool obs_module_load(void)
|
|||
void obs_module_unload(void)
|
||||
{
|
||||
update_info_destroy(update_info);
|
||||
unload_twitch_data();
|
||||
dstr_free(&module_name);
|
||||
}
|
||||
|
|
|
|||
224
plugins/rtmp-services/twitch.c
Normal file
224
plugins/rtmp-services/twitch.c
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
#include <file-updater/file-updater.h>
|
||||
#include <util/threading.h>
|
||||
#include <util/platform.h>
|
||||
#include <obs-module.h>
|
||||
#include <util/dstr.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#include "twitch.h"
|
||||
|
||||
static update_info_t *twitch_update_info = NULL;
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool ingests_refreshed = false;
|
||||
static bool ingests_refreshing = false;
|
||||
static bool ingests_loaded = false;
|
||||
|
||||
struct ingest {
|
||||
char *name;
|
||||
char *url;
|
||||
};
|
||||
|
||||
static DARRAY(struct ingest) cur_ingests;
|
||||
|
||||
static void free_ingests(void)
|
||||
{
|
||||
for (size_t i = 0; i < cur_ingests.num; i++) {
|
||||
struct ingest *ingest = cur_ingests.array + i;
|
||||
bfree(ingest->name);
|
||||
bfree(ingest->url);
|
||||
}
|
||||
|
||||
da_free(cur_ingests);
|
||||
}
|
||||
|
||||
static bool load_ingests(const char *json, bool write_file)
|
||||
{
|
||||
json_t *root;
|
||||
json_t *ingests;
|
||||
bool success = false;
|
||||
char *cache_old;
|
||||
char *cache_new;
|
||||
size_t count;
|
||||
|
||||
root = json_loads(json, 0, NULL);
|
||||
if (!root)
|
||||
goto finish;
|
||||
|
||||
ingests = json_object_get(root, "ingests");
|
||||
if (!ingests)
|
||||
goto finish;
|
||||
|
||||
count = json_array_size(ingests);
|
||||
if (count <= 1 && cur_ingests.num)
|
||||
goto finish;
|
||||
|
||||
free_ingests();
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
json_t *item = json_array_get(ingests, i);
|
||||
json_t *item_name = json_object_get(item, "name");
|
||||
json_t *item_url = json_object_get(item, "url_template");
|
||||
struct ingest ingest = {0};
|
||||
struct dstr url = {0};
|
||||
|
||||
if (!item_name || !item_url)
|
||||
continue;
|
||||
|
||||
const char *url_str = json_string_value(item_url);
|
||||
const char *name_str = json_string_value(item_name);
|
||||
|
||||
/* At the moment they currently mis-spell "deprecated",
|
||||
* but that may change in the future, so blacklist both */
|
||||
if (strstr(name_str, "deprecated") != NULL ||
|
||||
strstr(name_str, "depracated") != NULL)
|
||||
continue;
|
||||
|
||||
dstr_copy(&url, url_str);
|
||||
dstr_replace(&url, "/{stream_key}", "");
|
||||
|
||||
ingest.name = bstrdup(name_str);
|
||||
ingest.url = url.array;
|
||||
|
||||
da_push_back(cur_ingests, &ingest);
|
||||
}
|
||||
|
||||
if (!cur_ingests.num)
|
||||
goto finish;
|
||||
|
||||
success = true;
|
||||
|
||||
if (!write_file)
|
||||
goto finish;
|
||||
|
||||
cache_old = obs_module_config_path("twitch_ingests.json");
|
||||
cache_new = obs_module_config_path("twitch_ingests.new.json");
|
||||
|
||||
os_quick_write_utf8_file(cache_new, json, strlen(json), false);
|
||||
os_safe_replace(cache_old, cache_new, NULL);
|
||||
|
||||
bfree(cache_old);
|
||||
bfree(cache_new);
|
||||
|
||||
finish:
|
||||
if (root)
|
||||
json_decref(root);
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool twitch_ingest_update(void *param, struct file_download_data *data)
|
||||
{
|
||||
bool success;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
success = load_ingests((const char *)data->buffer.array, true);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
if (success) {
|
||||
os_atomic_set_bool(&ingests_refreshed, true);
|
||||
os_atomic_set_bool(&ingests_loaded, true);
|
||||
}
|
||||
|
||||
UNUSED_PARAMETER(param);
|
||||
return true;
|
||||
}
|
||||
|
||||
void twitch_ingests_lock(void)
|
||||
{
|
||||
pthread_mutex_lock(&mutex);
|
||||
}
|
||||
|
||||
void twitch_ingests_unlock(void)
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
size_t twitch_ingest_count(void)
|
||||
{
|
||||
return cur_ingests.num;
|
||||
}
|
||||
|
||||
struct twitch_ingest twitch_ingest(size_t idx)
|
||||
{
|
||||
struct twitch_ingest ingest;
|
||||
|
||||
if (cur_ingests.num <= idx) {
|
||||
ingest.name = NULL;
|
||||
ingest.url = NULL;
|
||||
} else {
|
||||
ingest = *(struct twitch_ingest*)(cur_ingests.array + idx);
|
||||
}
|
||||
|
||||
return ingest;
|
||||
}
|
||||
|
||||
void init_twitch_data(void)
|
||||
{
|
||||
da_init(cur_ingests);
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
}
|
||||
|
||||
extern const char *get_module_name(void);
|
||||
|
||||
void twitch_ingests_refresh(int seconds)
|
||||
{
|
||||
if (os_atomic_load_bool(&ingests_refreshed))
|
||||
return;
|
||||
|
||||
if (!os_atomic_load_bool(&ingests_refreshing)) {
|
||||
os_atomic_set_bool(&ingests_refreshing, true);
|
||||
|
||||
twitch_update_info = update_info_create_single(
|
||||
"[twitch ingest update] ",
|
||||
get_module_name(),
|
||||
"https://ingest.twitch.tv/api/v2/ingests",
|
||||
twitch_ingest_update, NULL);
|
||||
}
|
||||
|
||||
/* wait five seconds max when loading ingests for the first time */
|
||||
if (!os_atomic_load_bool(&ingests_loaded)) {
|
||||
for (int i = 0; i < seconds * 100; i++) {
|
||||
if (os_atomic_load_bool(&ingests_refreshed)) {
|
||||
break;
|
||||
}
|
||||
os_sleep_ms(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void load_twitch_data(void)
|
||||
{
|
||||
char *twitch_cache = obs_module_config_path("twitch_ingests.json");
|
||||
|
||||
struct ingest def = {
|
||||
.name = bstrdup("Default"),
|
||||
.url = bstrdup("rtmp://live.twitch.tv/app")
|
||||
};
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
da_push_back(cur_ingests, &def);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
if (os_file_exists(twitch_cache)) {
|
||||
char *data = os_quick_read_utf8_file(twitch_cache);
|
||||
bool success;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
success = load_ingests(data, false);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
if (success) {
|
||||
os_atomic_set_bool(&ingests_loaded, true);
|
||||
}
|
||||
|
||||
bfree(data);
|
||||
}
|
||||
|
||||
bfree(twitch_cache);
|
||||
}
|
||||
|
||||
void unload_twitch_data(void)
|
||||
{
|
||||
update_info_destroy(twitch_update_info);
|
||||
free_ingests();
|
||||
pthread_mutex_destroy(&mutex);
|
||||
}
|
||||
11
plugins/rtmp-services/twitch.h
Normal file
11
plugins/rtmp-services/twitch.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
struct twitch_ingest {
|
||||
const char *name;
|
||||
const char *url;
|
||||
};
|
||||
|
||||
extern void twitch_ingests_lock(void);
|
||||
extern void twitch_ingests_unlock(void);
|
||||
extern size_t twitch_ingest_count(void);
|
||||
extern struct twitch_ingest twitch_ingest(size_t idx);
|
||||
Loading…
Add table
Add a link
Reference in a new issue