OBS Studio — obs-websocket
Fungit
编辑于 2021年12月08日 12:33
收录于文集
共5篇

What is obs-websocket ?

WebSockets API for OBS Studio. or Remote-control of OBS Studio through WebSocket 


Environment

代码块
JavaScript
自动换行
复制代码
'os': 'Ubuntu 20.04.3 LTS (Focal Fossa)',
'python': 'Python 3.8.10',
'obs-studio-version': '27.1.3',
// obs-websocket: https://github.com/obsproject/obs-websocket/tree/4.x-current
'obs-websocket-version': '4.9.1',
// simpleobsws: https://github.com/IRLToolkit/simpleobsws/tree/simpleobsws-4.x
'simpleobsws': '1.2.1'
复制成功


安装环境

  • OBS Studio

我的系统是ubuntu 20.04 lts,安装过程可以参考官方文档,比较简单,目前obs还不支持arm架构的.

https://github.com/obsproject/obs-studio/wiki/install-instructions#ubuntumint-installation

代码块
Shell
自动换行
复制代码
sudo apt install ffmpeg
# 虚拟摄像头
sudo apt install v4l2loopback-dkms

sudo add-apt-repository ppa:obsproject/obs-studio
sudo apt update
sudo apt install obs-studio
复制成功


  • obs-websocket and simpleobsws

现在主分之是5.x版本,我用的是4.x版本,注意区别.

https://github.com/obsproject/obs-websocket/tree/4.x-current https://github.com/IRLToolkit/simpleobsws/tree/simpleobsws-4.x

代码块
Shell
自动换行
复制代码
# install obs-websocket
wget https://github.com/obsproject/obs-websocket/releases/download/4.9.1/obs-websocket_4.9.1-1_amd64.deb 
dkpg -i obs-websocket_4.9.1-1_amd64.deb 

# install sampleobs

pip3 install simpleobsws
复制成功


配置与测试

安装完obs-websocket之后,记得重启obs,之后点击"工具&#​34; --> "websocket服务器&#​34;,然后配置obs-websocket.

WebSocket 服务器设置

记得设置密码,还有防火墙是否开启外部网络访问,我的是本地调用,故添加ufw禁止22333端口的访问

代码块
Shell
自动换行
复制代码
#禁止
ufw deny 22333

#允许
ufw allow 22333

# 删除规则

ufw delete deny 22333
# or
ufw ufw allow 22333
复制成功

api调用我使用的是sample_request方式,request方式.

https://github.com/IRLToolkit/simpleobsws/blob/simpleobsws-4.x/samples/sample_request.py

代码块
Shell
自动换行
复制代码
import asyncio
import simpleobsws

loop = asyncio.get_event_loop()
ws = simpleobsws.obsws(host='127.0.0.1', port=22333, password='Fungit.org', loop=loop) 
async def make_request():
    await ws.connect() #
    result = await ws.call('GetVersion') 
    print(result) 
    await ws.disconnect() 
    
loop.run_until_complete(make_request())
复制成功

执行之后,大概会返回这样的json数据

代码块
JavaScript
自动换行
复制代码
{'available-requests': 'AddFilterToSource,AddSceneItem,Authenticate,BroadcastCustomMessage,CreateScene,CreateSource,DeleteSceneItem,DisableStudioMode,DuplicateSceneItem,EnableStudioMode,ExecuteBatch,GetAudioActive,GetAudioMonitorType,GetAudioTracks,GetAuthRequired,GetBrowserSourceProperties,GetCurrentProfile,GetCurrentScene,GetCurrentSceneCollection,GetCurrentTransition,GetFilenameFormatting,GetMediaDuration,GetMediaSourcesList,GetMediaState,GetMediaTime,GetMute,GetOutputInfo,GetPreviewScene,GetRecordingFolder,GetRecordingStatus,GetReplayBufferStatus,GetSceneItemList,GetSceneItemProperties,GetSceneList,GetSceneTransitionOverride,GetSourceActive,GetSourceDefaultSettings,GetSourceFilterInfo,GetSourceFilters,GetSourceSettings,GetSourcesList,GetSourceTypesList,GetSpecialSources,GetStats,GetStreamingStatus,GetStreamSettings,GetStudioModeStatus,GetSyncOffset,GetTextFreetype2Properties,GetTextGDIPlusProperties,GetTransitionDuration,GetTransitionList,GetTransitionPosition,GetTransitionSettings,GetVersion,GetVideoInfo,GetVirtualCamStatus,GetVolume,ListOutputs,ListProfiles,ListSceneCollections,MoveSourceFilter,NextMedia,OpenProjector,PauseRecording,PlayPauseMedia,PreviousMedia,RefreshBrowserSource,ReleaseTBar,RemoveFilterFromSource,RemoveSceneTransitionOverride,ReorderSceneItems,ReorderSourceFilter,ResetSceneItem,RestartMedia,ResumeRecording,SaveReplayBuffer,SaveStreamSettings,ScrubMedia,SendCaptions,SetAudioMonitorType,SetAudioTracks,SetBrowserSourceProperties,SetCurrentProfile,SetCurrentScene,SetCurrentSceneCollection,SetCurrentTransition,SetFilenameFormatting,SetHeartbeat,SetMediaTime,SetMute,SetPreviewScene,SetRecordingFolder,SetSceneItemCrop,SetSceneItemPosition,SetSceneItemProperties,SetSceneItemRender,SetSceneItemTransform,SetSceneTransitionOverride,SetSourceFilterSettings,SetSourceFilterVisibility,SetSourceName,SetSourceRender,SetSourceSettings,SetStreamSettings,SetSyncOffset,SetTBarPosition,SetTextFreetype2Properties,SetTextGDIPlusProperties,SetTransitionDuration,SetTransitionSettings,SetVolume,Sleep,StartOutput,StartRecording,StartReplayBuffer,StartStopRecording,StartStopReplayBuffer,StartStopStreaming,StartStopVirtualCam,StartStreaming,StartVirtualCam,StopMedia,StopOutput,StopRecording,StopReplayBuffer,StopStreaming,StopVirtualCam,TakeSourceScreenshot,ToggleMute,ToggleStudioMode,TransitionToProgram,TriggerHotkeyByName,TriggerHotkeyBySequence', 'obs-studio-version': '27.1.3', 'obs-websocket-version': '4.9.1', 'status': 'ok', 'supported-image-export-formats': 'bmp,cur,icns,ico,jpeg,jpg,pbm,pgm,png,ppm,tif,tiff,wbmp,webp,xbm,xpm', 'version': 1.1}
复制成功

这串数据可以看出当前可用的请求available-requests,和版本信息等'obs-studio-version&#​39;: '27.1.3&#​39;, 'obs-websocket-version&#​39;: '4.9.1&#​39;.

最后的最后,还是看obs-websocket的api文档,注意是Request.

https://github.com/obsproject/obs-websocket/blob/4.x-current/docs/generated/protocol.md#requests


直播间

直播间目前弹幕控制obs的代码,有空再聊弹幕姬那部分了.

ps: 由于我的直播视频是通过streamlink打开的,所以需要shell\screen,如果是捕获浏览器窗口可忽略call shell部分

代码块
Python
自动换行
复制代码
    async def obs_ws_action(self, actions, name):
        try:
            ws = simpleobsws.obsws(host='127.0.0.1', port=22333, password='Fungit.org')
            print("action is :" + name)
            await ws.connect()

            # 切换直播和视频
            if actions == "ChangeMain" or actions == "ChangeVideo":
                print("切换直播")
                data_1 = {'sourceName': 'Activity'}
                data_2 = {'sourceName': 'MainVideo'}
                if actions == "ChangeMain":
                    # call shell
                    data_1 = {'sourceName': 'MainVideo'}
                    data_2 = {'sourceName': 'Activity'}
                result = await ws.call('RestartMedia', data_1)
                await asyncio.sleep(1)
                result = await ws.call('StopMedia', data_2)
                print(result)

            if actions == "OpenVICI" or actions == "CloseVICI":
                print("打开关闭副镜头")
                data_1 = {'sourceName': 'VICI'}
                if actions == "OpenVICI":
                    # call shell
                    result = await ws.call('RestartMedia', data_1)
                    return
                result = await ws.call('StopMedia', data_1)
                print(result)

            elif actions == "RestartMedia" :
                MainVideo = {'sourceName': 'MainVideo'}
                result = await ws.call('RestartMedia', MainVideo)
                print(result)

            elif actions == "RestartStreaming":
                print("重启推流")
                result = await ws.call('StopStreaming')
                await asyncio.sleep(3)
                data = {}
                result = await ws.call('StartStreaming', data)
                print(result)

            else:
                print("nothing")

            print(result)
            await ws.disconnect()

        except Exception as e:
            print(e)
            await ws.disconnect()
            pass
复制成功

所以直播间的obs控制弹幕为(需要权限):

  1. 弹幕关键字重启、刷新主镜头,注意是以@开头;  刷新流和主镜头:@RestartMedia、@RestartMain、@重启

  2. 切换镜头:两个画面,一个是直播的镜头,一个是录像视频;  直播画面:@切换主镜头、@切换直播、@ChangeMain ;  录像画面:@切换录像、@切换视频、@ChangeActivity

  3. 显示/隐藏副镜头;  显示副镜头:@显示副镜头、@打开副镜头、@OpenVICI; 隐藏副镜头:@隐藏副镜头、@关闭副镜头、@CloseVICI

最后讲下手机怎么加入应援团:

因为玩B站比较晚,甚至不知道应援团还有二维码的存在,无意中看到一张应援团的二维码,通过扫码之后得到一个链接

网页链接​;params=eyJpZCI6MjIxMDgxOTc5LCJ0eXBlIjoxfQ==

虽然不知道params那个部分是什么,但是熟悉编码的都有印象,拿去base64解码之后,得到的是

https://www.base64decode.org/

代码块
JavaScript
自动换行
复制代码
{"id":221081979,"type":1}
复制成功

得到的json数据很容易看出来,id就是应援团的id,type暂时不知道作用,默认就好了,所以你想生成自己的应援团链接,把上面id改为你的应援团id,然后拿去encode,替换params=“应援团base64”

https://www.base64encode.org/

我的手机应援团入口:网页链接​;params=eyJpZCI6MjIxMDgxOTc5LCJ0eXBlIjoxfQ==