海康威视云台相机的python sdk使用(云台控制)
SDK(Software Development Kit)是软件开发工具包的缩写,它是一组用于开发特定软件或应用程序的工具、库和文档的集合。SDK提供了开发所需的资源和接口,帮助开发者更高效地构建应用程序。
SDK通常包含以下内容:
工具:SDK提供了一系列开发工具,如编译器、调试器、IDE(集成开发环境)等,用于编写、调试和测试代码。
库:SDK中的库是预先编译好的可重用代码模块,包含常见的功能和算法,开发者可以直接调用这些库来简化开发过程。
示例代码:SDK通常附带一些示例代码,展示如何使用SDK提供的功能和接口,帮助开发者快速上手并理解开发流程。
文档:SDK提供详细的文档,包括API参考、开发指南、示例代码解释等,帮助开发者了解SDK的功能和使用方法。
依赖项:SDK可能需要依赖其他软件或库,例如操作系统、第三方库等,开发者需要满足这些依赖关系才能使用SDK。
SDK的作用是简化开发过程,提供开发所需的资源和接口,节省开发者的时间和精力。通过使用SDK,开发者可以快速构建功能丰富、高效的应用程序,而无需从头开始编写所有的代码和功能。
1.海康SDK下载
海康开放平台


选择你自己需要的平台,主要是需要里面的库文件。如果边缘设备就选ARM的,Ubuntu系统就选普通Linux
下载好解压后
进入以下路径
海康威视-HCNetSDKV6.1.9.48_build20230410_win64---Demo示例---5- Python开发示例---1-预览取流解码Demo
1.找到这个lib路径,里面应该是空的

看需要选择win或者linux

2.返回主目录,选择库文件,复制全部文件(实际按官方文档只需要部分库文件,不过可以傻瓜式全部打包),粘贴到上面的lib文件夹的win文件中
下面是官方文档的操作说明
1. 更新设备网络SDK时,SDK开发包【库文件】里的HCNetSDK.dll、HCCore.dll、HCNetSDKCom文件夹、libssl-1_1.dll、libcrypto-1_1.dll、hlog.dll、hpr.dll、zlib1.dll、PlayCtrl.dll、SuperRender.dll、AudioRender.dll等文件均要加载到程序里面,【HCNetSDKCom文件夹】(包含里面的功能组件dll库文件)需要和HCNetSDK.dll、HCCore.dll一起加载,放在同一个目录下,且HCNetSDKCom文件夹名不能修改。
2. 如果自行开发软件不能正常实现相应功能,而且程序没有指定加载的dll库路径,请在程序运行的情况下尝试删除HCNetSDK.dll。如果可以删除,说明程序可能调用到系统盘Windows->System32目录下的dll文件,建议删除或者更新该目录下的相关dll文件;如果不能删除,dll文件右键选择属性确认SDK库版本。
3. 如按上述步骤操作后还是不能实现相应功能,请根据NET_DVR_GetLastError返回的错误号判断原因。

下面代码可以进行简单测试,试试云台是否可动
# coding=utf-8import os
import platform
import tkinter
from tkinter import *
from HCNetSDK import *
from PlayCtrl import *
from time import sleep# 登录的设备信息
DEV_IP = create_string_buffer(b'10.17.35.41')
DEV_PORT = 8000
DEV_USER_NAME = create_string_buffer(b'admin')
DEV_PASSWORD = create_string_buffer(b'abcd1234')WINDOWS_FLAG = True
win = None # 预览窗口
funcRealDataCallBack_V30 = None # 实时预览回调函数,需要定义为全局的PlayCtrl_Port = c_long(-1) # 播放句柄
Playctrldll = None # 播放库
FuncDecCB = None # 播放库解码回调函数,需要定义为全局的# 获取当前系统环境
def GetPlatform():sysstr = platform.system()print('' + sysstr)if sysstr != "Windows":global WINDOWS_FLAGWINDOWS_FLAG = False# 设置SDK初始化依赖库路径
def SetSDKInitCfg():# 设置HCNetSDKCom组件库和SSL库加载路径# print(os.getcwd())if WINDOWS_FLAG:strPath = os.getcwd().encode('gbk')sdk_ComPath = NET_DVR_LOCAL_SDK_PATH()sdk_ComPath.sPath = strPathObjdll.NET_DVR_SetSDKInitCfg(2, byref(sdk_ComPath))Objdll.NET_DVR_SetSDKInitCfg(3, create_string_buffer(strPath + b'\libcrypto-1_1-x64.dll'))Objdll.NET_DVR_SetSDKInitCfg(4, create_string_buffer(strPath + b'\libssl-1_1-x64.dll'))else:strPath = os.getcwd().encode('utf-8')sdk_ComPath = NET_DVR_LOCAL_SDK_PATH()sdk_ComPath.sPath = strPathObjdll.NET_DVR_SetSDKInitCfg(2, byref(sdk_ComPath))Objdll.NET_DVR_SetSDKInitCfg(3, create_string_buffer(strPath + b'/libcrypto.so.1.1'))Objdll.NET_DVR_SetSDKInitCfg(4, create_string_buffer(strPath + b'/libssl.so.1.1'))def LoginDev(Objdll):# 登录注册设备device_info = NET_DVR_DEVICEINFO_V30()lUserId = Objdll.NET_DVR_Login_V30(DEV_IP, DEV_PORT, DEV_USER_NAME, DEV_PASSWORD, byref(device_info))return (lUserId, device_info)def DecCBFun(nPort, pBuf, nSize, pFrameInfo, nUser, nReserved2):# 解码回调函数if pFrameInfo.contents.nType == 3:# 解码返回视频YUV数据,将YUV数据转成jpg图片保存到本地# 如果有耗时处理,需要将解码数据拷贝到回调函数外面的其他线程里面处理,避免阻塞回调导致解码丢帧sFileName = ('../../pic/test_stamp[%d].jpg'% pFrameInfo.contents.nStamp)nWidth = pFrameInfo.contents.nWidthnHeight = pFrameInfo.contents.nHeightnType = pFrameInfo.contents.nTypedwFrameNum = pFrameInfo.contents.dwFrameNumnStamp = pFrameInfo.contents.nStampprint(nWidth, nHeight, nType, dwFrameNum, nStamp, sFileName)lRet = Playctrldll.PlayM4_ConvertToJpegFile(pBuf, nSize, nWidth, nHeight, nType, c_char_p(sFileName.encode()))if lRet == 0:print('PlayM4_ConvertToJpegFile fail, error code is:', Playctrldll.PlayM4_GetLastError(nPort))else:print('PlayM4_ConvertToJpegFile success')def RealDataCallBack_V30(lPlayHandle, dwDataType, pBuffer, dwBufSize, pUser):# 码流回调函数if dwDataType == NET_DVR_SYSHEAD:# 设置流播放模式Playctrldll.PlayM4_SetStreamOpenMode(PlayCtrl_Port, 0)# 打开码流,送入40字节系统头数据if Playctrldll.PlayM4_OpenStream(PlayCtrl_Port, pBuffer, dwBufSize, 1024*1024):# 设置解码回调,可以返回解码后YUV视频数据global FuncDecCBFuncDecCB = DECCBFUNWIN(DecCBFun)Playctrldll.PlayM4_SetDecCallBackExMend(PlayCtrl_Port, FuncDecCB, None, 0, None)# 开始解码播放if Playctrldll.PlayM4_Play(PlayCtrl_Port, cv.winfo_id()):print(u'播放库播放成功')else:print(u'播放库播放失败')else:print(u'播放库打开流失败')elif dwDataType == NET_DVR_STREAMDATA:Playctrldll.PlayM4_InputData(PlayCtrl_Port, pBuffer, dwBufSize)else:print (u'其他数据,长度:', dwBufSize)def OpenPreview(Objdll, lUserId, callbackFun):'''打开预览'''preview_info = NET_DVR_PREVIEWINFO()preview_info.hPlayWnd = 0preview_info.lChannel = 1 # 通道号preview_info.dwStreamType = 0 # 主码流preview_info.dwLinkMode = 0 # TCPpreview_info.bBlocked = 1 # 阻塞取流# 开始预览并且设置回调函数回调获取实时流数据lRealPlayHandle = Objdll.NET_DVR_RealPlay_V40(lUserId, byref(preview_info), callbackFun, None)return lRealPlayHandledef InputData(fileMp4, Playctrldll):while True:pFileData = fileMp4.read(4096)if pFileData is None:breakif not Playctrldll.PlayM4_InputData(PlayCtrl_Port, pFileData, len(pFileData)):breakif __name__ == '__main__':# 创建窗口win = tkinter.Tk()#固定窗口大小win.resizable(0, 0)win.overrideredirect(True)sw = win.winfo_screenwidth()# 得到屏幕宽度sh = win.winfo_screenheight()# 得到屏幕高度# 窗口宽高ww = 512wh = 384x = (sw - ww) / 2y = (sh - wh) / 2win.geometry("%dx%d+%d+%d" % (ww, wh, x, y))# 创建退出按键b = Button(win, text='退出', command=win.quit)b.pack()# 创建一个Canvas,设置其背景色为白色cv = tkinter.Canvas(win, bg='white', width=ww, height=wh)cv.pack()# 获取系统平台GetPlatform()# 加载库,先加载依赖库if WINDOWS_FLAG:os.chdir(r'./lib/win')Objdll = ctypes.CDLL(r'./HCNetSDK.dll') # 加载网络库Playctrldll = ctypes.CDLL(r'./PlayCtrl.dll') # 加载播放库else:os.chdir(r'./lib/linux')Objdll = cdll.LoadLibrary(r'./libhcnetsdk.so')Playctrldll = cdll.LoadLibrary(r'./libPlayCtrl.so')SetSDKInitCfg() # 设置组件库和SSL库加载路径# 初始化DLLObjdll.NET_DVR_Init()# 启用SDK写日志Objdll.NET_DVR_SetLogToFile(3, bytes('./SdkLog_Python/', encoding="utf-8"), False)# 获取一个播放句柄if not Playctrldll.PlayM4_GetPort(byref(PlayCtrl_Port)):print(u'获取播放库句柄失败')# 登录设备(lUserId, device_info) = LoginDev(Objdll)if lUserId < 0:err = Objdll.NET_DVR_GetLastError()print('Login device fail, error code is: %d' % Objdll.NET_DVR_GetLastError())# 释放资源Objdll.NET_DVR_Cleanup()exit()# 定义码流回调函数funcRealDataCallBack_V30 = REALDATACALLBACK(RealDataCallBack_V30)# 开启预览lRealPlayHandle = OpenPreview(Objdll, lUserId, funcRealDataCallBack_V30)if lRealPlayHandle < 0:print ('Open preview fail, error code is: %d' % Objdll.NET_DVR_GetLastError())# 登出设备Objdll.NET_DVR_Logout(lUserId)# 释放资源Objdll.NET_DVR_Cleanup()exit()#show Windowswin.mainloop()# 开始云台控制lRet = Objdll.NET_DVR_PTZControl(lRealPlayHandle, PAN_LEFT, 0)if lRet == 0:print ('Start ptz control fail, error code is: %d' % Objdll.NET_DVR_GetLastError())else:print ('Start ptz control success')# 转动一秒sleep(1)# 停止云台控制lRet = Objdll.NET_DVR_PTZControl(lRealPlayHandle, PAN_LEFT, 1)if lRet == 0:print('Stop ptz control fail, error code is: %d' % Objdll.NET_DVR_GetLastError())else:print('Stop ptz control success')# 关闭预览Objdll.NET_DVR_StopRealPlay(lRealPlayHandle)# 停止解码,释放播放库资源if PlayCtrl_Port.value > -1:Playctrldll.PlayM4_Stop(PlayCtrl_Port)Playctrldll.PlayM4_CloseStream(PlayCtrl_Port)Playctrldll.PlayM4_FreePort(PlayCtrl_Port)PlayCtrl_Port = c_long(-1)# 登出设备Objdll.NET_DVR_Logout(lUserId)# 释放资源Objdll.NET_DVR_Cleanup()
如果出现
Login device fail, error code is: 7Login device fail, error code is: 1
注意可能是账号密码出错,也可能没有以根目录打开,没有找到相关文件。
如果无法连接到某个dll库,Linux里无法连接到.so的情况,注意可能是dll文件在解压时损坏了,或者文件错误,如ARM和Linux不兼容等。
