Elixir 通過 ExOnvif 庫,Onvif 協議可以控制IP攝像機等設備,這篇文章記錄:使用ExOnvif庫,給視頻流疊加文字,使用ExOnvif庫的接口模塊:ExOnvif.Media、ExOnvif.Media2。
ExOnvif官方文檔
此文章內容:視頻流疊加文字,關于Elixir通過ONVIF協議實現PTZ控制、視頻流獲取等指令,可以查看我的其他文章。點擊查看主頁
1. Media2和Media的核心關系:演進與替代
在 Onvif 協議中,Media2 是 Media 的升級版,
Media (Profile S): 是ONVIF基礎版媒體服務,最早在ONVIF核心規范中定義。它提供了基本的視頻流獲取、快照、音頻、視頻編碼配置等功能。絕大多數支持ONVIF的舊設備都實現了此服務。Media2 (Profile T): 是ONVIF第二代媒體服務,在 media 的基礎上進行了重構和大幅增強。它是 Profile T 強制要求的標準服務。新發布的、功能更豐富的設備(尤其是支持H.265等新編碼的設備)通常會同時支持 media 和 media2 或僅支持 media2。
關系總結: media2 并非要完全廢棄 media,而是在保持向后兼容性的同時,提供了一個更先進的替代方案。兩者在網絡上可以共存。
2. 獲取OSD
獲取OSD有兩種方式
- get_osd(device, token) # get the osd by token
- get_osds(device) # get the osds
設置OSD的方式
- set_osd(device, osd) #set the osd
- create_osd(device, osd) # create the osd
更新邏輯
- 首先先通過get_osds函數獲取所有的osds,
- 取到需要更新的osd的token
- 調用set或create函數,修改或創建新的osd text
3. 完整的代碼示例
defmodule MvOnvif.Action douse GenServer@moduledoc """自定義的Onvif的部分協議獲取當前狀態(exonvif)absolute move調用攝像頭到指定位置,continuous move攝像頭連續移動調用指定預置位停止運動"""import ExOnvif.Utils.XmlBuilderimport SweetXmlalias ExOnvif.Devicealias ExOnvif.Media2# 初始化device設備defp get_device(uri) when not is_nil(uri) do%{host: host, userinfo: userinfo} = URI.parse(uri)[user, pw] = String.split(userinfo, ":")Device.new("http://" <> host, user, pw);enddefp get_device(uri) do:errorend # 獲取profiletoken標識符defp get_main_stream_profile_token(device) doprofiles = Media2.get_profiles(device)case profiles do{:ok, list} -> {:ok, hd(list).reference_token}_ -> "something went wrong"endend# 獲取文字疊加def get_osds(uri) dowith {:ok, device} <- get_device(uri) doExOnvif.Media.get_osds(device)endend# 創建/更新 文字疊加def create_osd({ip, username, password}, text) dowith {:ok, device} <- get_device(ip, username, password),{:ok, profile_token} <- get_main_stream_profile_token(device),{:ok, source} <- ExOnvif.Media2.get_video_source_configurations(device, [profile_token: profile_token]),{:ok, osd_list} <- ExOnvif.Media.get_osds(device)do%{source_token: source_token} = hd(source) #默認取主視頻流if length(osd_list) > 2 do # 我取的是第三個osd%{token: osd_token} = List.last(osd_list)osd = make_osd(source_token, text, osd_token)ExOnvif.Media.set_osd(device, osd)elseosd = make_osd(source_token, text)ExOnvif.Media.create_osd(device, osd)endendend# %ExOnvif.Media.OSD實例defp make_osd(source_token, text \\ "", token \\ nil) do%ExOnvif.Media.OSD{token: token,video_source_configuration_token: source_token,text_string: %ExOnvif.Media.OSD.TextString{is_persistent_text: true,type: :plain,plain_text: text},type: :text,position: %ExOnvif.Media.OSD.Position{type: :upper_left,pos: %{x: 21, y: 1}}}end
end
4. xml文件示例
獲取osds的xml
<wsdl:GetOSDs><wsdl:ConfigurationToken>VideoSourceToken_1</wsdl:ConfigurationToken>
</wsdl:GetOSDs>
修改osd的xml
<SOAP-ENV:Body><wsdl:SetOSD><wsdl:OSDToken>OSDToken_001</wsdl:OSDToken> <!-- 要修改的OSD令牌 --><wsdl:OSD><tt:Position><tt:Pos><tt:x>0.85</tt:x><tt:y>0.05</tt:y></tt:Pos></tt:Position><tt:TextString><tt:FontSize>16</tt:FontSize><tt:FontColor>0xFF0000</tt:FontColor> <!-- 改為紅色 --><tt:PlainText>MAIN GATE - CAM01</tt:PlainText></tt:TextString></wsdl:OSD></wsdl:SetOSD>
</SOAP-ENV:Body>
創建osd的xml
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelopexmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"xmlns:wsdl="http://www.onvif.org/ver20/device/wsdl"xmlns:tt="http://www.onvif.org/ver10/schema"><SOAP-ENV:Header><!-- 安全認證頭(同前) --></SOAP-ENV:Header><SOAP-ENV:Body><wsdl:CreateOSD><wsdl:OSD><tt:VideoSourceConfigurationToken>VideoSourceToken_1</tt:VideoSourceConfigurationToken><tt:Type>Text</tt:Type><tt:Position><tt:Type>Custom</tt:Type> <!-- 或 UpperLeft/UpperRight/LowerLeft/LowerRight --><tt:Pos><tt:x>0.8</tt:x> <!-- 0-1.0 水平位置 --><tt:y>0.1</tt:y> <!-- 0-1.0 垂直位置 --></tt:Pos></tt:Position><tt:TextString><tt:Type>Plain</tt:Type> <!-- 或 Date/Time/DateAndTime --><tt:DateFormat>yyyy-MM-dd</tt:DateFormat><tt:TimeFormat>HH:mm:ss</tt:TimeFormat><tt:FontSize>14</tt:FontSize><tt:FontColor>0x00FF00</tt:FontColor> <!-- RGB 格式: 0xRRGGBB --><tt:BackgroundColor>0x000000</tt:BackgroundColor><tt:PlainText>Camera 01 - Main Gate</tt:PlainText><tt:Extension><tt:IsPersistentText>true</tt:IsPersistentText></tt:Extension></tt:TextString></wsdl:OSD></wsdl:CreateOSD></SOAP-ENV:Body>
</SOAP-ENV:Envelope>