一、前言
搞定了實時預覽后,另一個功能就是錄像回放,錄像回放和視頻點播功能完全一致,唯一的區別就是發送點播的sdp信息中攜帶了開始時間和結束時間,因為是錄像文件,所以有這個時間,而實時視頻預覽這個對應的值是0,錄像文件是可以切換播放進度的,實時視頻是無法切換進度的,因為當前是7點鐘,不可能切換到未來的某個時間點查看到對應的視頻畫面,遇到過幾個用戶居然希望問為何實時預覽功能不支持切換進度,這個從邏輯層面來說就是無法實現的。
要實現錄像回放,首先就是要拿到錄像文件,也就是錄像文件查詢,發個查詢指令到設備端,會返回錄像文件的信息,這里有個細節強調下,返回的錄像文件信息并不是在一個xml中,可能一個xml中有多個錄像文件信息,也可能只有一個,不同廠家約定不同,都是合規的,所以在tcp模式交互的sip數據中,很可能出現粘包的情況,需要自己取出來逐個解析,這個細節很多國標工具沒有實現。
在回放的過程中,還可以任意切換播放進度,不少廠家用的很老的機制實現的切換進度,也就是重新點播,這樣好處是兼容了各個國標版本,壞處是相當于重新點播,切換過程會黑屏中斷2s左右。其實國標協議就提供了切換播放進度的sip協議,只需要發給設備端即可,設備收到切換進度指令后,會立即用指定進度的開始的位置發流過來,這邊收到后立即解析即可。
//查詢文件:服務端-》設備端
MESSAGE sip:34020000001320000002@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bKe9591d42a3cc4518a421b62aa668428d
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1038
To: <sip:34020000001320000002@192.168.0.64:5060>
Call-ID: a6d47d255da543e79f484475b49340de
CSeq: 41 MESSAGE
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 262
Content-Type: application/MANSCDP+xml
Contact: <sip:34020000002000000001@192.168.0.110:15060><?xml version="1.0" encoding="GB2312"?>
<Query><CmdType>RecordInfo</CmdType><SN>10035</SN><DeviceID>34020000001310000001</DeviceID><StartTime>2025-04-18T00:00:00</StartTime><EndTime>2025-04-19T23:59:59</EndTime><Type>all</Type>
</Query>//文件返回:設備端-》服務端
MESSAGE sip:34020000002000000001@3402000000 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.64:5060;rport;branch=z9hG4bK727604973
From: <sip:34020000001320000002@3402000000>;tag=593479594
To: <sip:34020000002000000001@3402000000>
Call-ID: 40677081
CSeq: 20 MESSAGE
Content-Type: Application/MANSCDP+xml
Max-Forwards: 70
User-Agent: IP Camera
Content-Length: 3161<?xml version="1.0" encoding="GB2312"?>
<Response>
<CmdType>RecordInfo</CmdType>
<SN>10035</SN>
<DeviceID>34020000001310000001</DeviceID>
<Name>hikangname</Name>
<SumNum>134</SumNum>
<RecordList Num="2">
<Item>
<DeviceID>34020000001310000001</DeviceID>
<Name>hikangname</Name>
<FilePath>file_path</FilePath>
<Address>Address 1</Address>
<StartTime>2025-04-18T10:23:02</StartTime>
<EndTime>2025-04-18T10:40:20</EndTime>
<Secrecy>0</Secrecy>
<Type>time</Type>
<FileSize>263094272</FileSize>
</Item>
<Item>
<DeviceID>34020000001310000001</DeviceID>
<Name>hikangname</Name>
<FilePath>file_path</FilePath>
<Address>Address 1</Address>
<StartTime>2025-04-18T10:40:20</StartTime>
<EndTime>2025-04-18T10:57:36</EndTime>
<Secrecy>0</Secrecy>
<Type>time</Type>
<FileSize>262488064</FileSize>
</Item>
</RecordList>
</Response>//點播請求:服務端-》設備端
INVITE sip:34020000001310000001@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK3d8b174429304a9d8af106f460debf9b
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1039
To: <sip:34020000001310000001@192.168.0.64:5060>
Call-ID: 2b3bf36cf7164ea0aac06fbd3e24680f
CSeq: 42 INVITE
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 342
Content-Type: application/sdp
Contact: <sip:34020000002000000001@192.168.0.110:15060>
Subject: 34020000001310000001:1000010003,34020000002000000001:0v=0
o=34020000001310000001 0 0 IN IP4 192.168.0.110
s=Download
u=34020000001310000001:0
c=IN IP4 192.168.0.110
t=1744946094 1744947129
m=video 6902 RTP/AVP 96 97 98
a=recvonly
a=setup:passive
a=connection:new
a=rtpmap:96 PS/90000
a=rtpmap:97 MPEG4/90000
a=rtpmap:98 H264/90000
a=downloadspeed:8
a=streamprofile:1
y=1000010003//請求應答:設備端-》服務端
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK3d8b174429304a9d8af106f460debf9b
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1039
To: <sip:34020000001310000001@192.168.0.64:5060>;tag=723451991
Call-ID: 2b3bf36cf7164ea0aac06fbd3e24680f
CSeq: 42 INVITE
Contact: <sip:34020000001320000002@192.168.0.64:5060>
Content-Type: application/sdp
User-Agent: IP Camera
Content-Length: 211v=0
o=34020000001320000002 539 539 IN IP4 192.168.0.64
s=Download
c=IN IP4 192.168.0.64
t=0 0
m=video 15060 RTP/AVP 96
a=setup:active
a=sendonly
a=rtpmap:96 PS/90000
a=filesize:262209536
y=1000010003//開始點播:服務端-》設備端
ACK sip:34020000001320000002@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK3d8b174429304a9d8af106f460debf9b
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1039
To: <sip:34020000001310000001@192.168.0.64:5060>;tag=723451991
Call-ID: 2b3bf36cf7164ea0aac06fbd3e24680f
CSeq: 42 ACK//暫停播放:服務端-》設備端
INFO sip:34020000001310000001@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK28e2fc9dac8b421f9a8450a10933210d
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1039
To: <sip:34020000001310000001@192.168.0.64:5060>;tag=723451991
Call-ID: 2b3bf36cf7164ea0aac06fbd3e24680f
CSeq: 43 INFO
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 41
Content-Type: application/MANSRTSP
Contact: <sip:34020000002000000001@192.168.0.110:15060>PAUSE RTSP/1.0
CSeq: 1
PauseTime: now//繼續播放:服務端-》設備端
INFO sip:34020000001310000001@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK86d002cd67004d0487ed0000b652c1bd
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1039
To: <sip:34020000001310000001@192.168.0.64:5060>;tag=723451991
Call-ID: 2b3bf36cf7164ea0aac06fbd3e24680f
CSeq: 45 INFO
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 41
Content-Type: application/MANSRTSP
Contact: <sip:34020000002000000001@192.168.0.110:15060>PLAY RTSP/1.0
CSeq: 3
Range: npt=now-//切換速度:服務端-》設備端
INFO sip:34020000001310000001@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bKd790bfabeea74caaba1594708fb91ada
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1039
To: <sip:34020000001310000001@192.168.0.64:5060>;tag=723451991
Call-ID: 2b3bf36cf7164ea0aac06fbd3e24680f
CSeq: 46 INFO
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 34
Content-Type: application/MANSRTSP
Contact: <sip:34020000002000000001@192.168.0.110:15060>PLAY RTSP/1.0
CSeq: 4
Scale: 4//切換進度:服務端-》設備端
INFO sip:34020000001310000001@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bKeb9b6621c9e446c9912f48127ecf0932
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1039
To: <sip:34020000001310000001@192.168.0.64:5060>;tag=723451991
Call-ID: 2b3bf36cf7164ea0aac06fbd3e24680f
CSeq: 47 INFO
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 41
Content-Type: application/MANSRTSP
Contact: <sip:34020000002000000001@192.168.0.110:15060>PLAY RTSP/1.0
CSeq: 5
Range: npt=379-//下載請求:服務端-》設備端
INVITE sip:34020000001310000001@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK6a208da569eb44028e0d159f9f245386
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1041
To: <sip:34020000001310000001@192.168.0.64:5060>
Call-ID: 3bd33cd0f76c40e8b0d702b4212c74e5
CSeq: 50 INVITE
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 342
Content-Type: application/sdp
Contact: <sip:34020000002000000001@192.168.0.110:15060>
Subject: 34020000001310000001:1000010004,34020000002000000001:0v=0
o=34020000001310000001 0 0 IN IP4 192.168.0.110
s=Download
u=34020000001310000001:0
c=IN IP4 192.168.0.110
t=1744856617 1744856620
m=video 6902 RTP/AVP 96 97 98
a=recvonly
a=setup:passive
a=connection:new
a=rtpmap:96 PS/90000
a=rtpmap:97 MPEG4/90000
a=rtpmap:98 H264/90000
a=downloadspeed:8
a=streamprofile:1
y=1000010004//請求應答:設備端-》服務端
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK6a208da569eb44028e0d159f9f245386
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1041
To: <sip:34020000001310000001@192.168.0.64:5060>;tag=1160726752
Call-ID: 3bd33cd0f76c40e8b0d702b4212c74e5
CSeq: 50 INVITE
Contact: <sip:34020000001320000002@192.168.0.64:5060>
Content-Type: application/sdp
User-Agent: IP Camera
Content-Length: 211v=0
o=34020000001320000002 2589 2589 IN IP4 192.168.0.64
s=Download
c=IN IP4 192.168.0.64
t=0 0
m=video 15060 RTP/AVP 96
a=setup:active
a=sendonly
a=rtpmap:96 PS/90000
a=filesize:1367160
y=1000010004//開始下載:服務端-》設備端
ACK sip:34020000001320000002@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK6a208da569eb44028e0d159f9f245386
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1041
To: <sip:34020000001310000001@192.168.0.64:5060>;tag=1160726752
Call-ID: 3bd33cd0f76c40e8b0d702b4212c74e5
CSeq: 50 ACK
二、效果圖
三、相關地址
- 國內站點:https://gitee.com/feiyangqingyun
- 國際站點:https://github.com/feiyangqingyun
- 個人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
- 文件地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取碼:01jf 文件名:bin_video_gb28181。
四、功能特點
- 支持設備注冊、注銷、心跳、校時、注冊認證、注銷認證等。
- 設備上線后可以手動獲取設備狀態、設備信息、配置信息、預置位信息等。
- 設備上線后自動獲取設備通道信息,包括中文通道名稱。識別到通道上線離線變化,會重新獲取該設備的所有通道信息。
- 支持視頻點播,可以分別點播主碼流和子碼流,內置rtp解包線程,解包后發給視頻播放組件解碼播放。
- 每個設備每個通道支持點播多個視頻,通過ssrc區分,支持共用端口和不同端口收流。
- 支持對某個設備下面所有通道、某個通道、某個通道對應的某個流分別關閉。
- 支持錄像文件查詢和回放,回放控制支持暫停播放、繼續播放、倍速播放、切換播放進度。
- 支持錄像文件下載,支持倍速比如8倍速下載,可同時多線程批量下載。
- 回放和下載同時支持IPC和NVR,比如攝像頭自帶的SD存儲卡錄像文件回放,NVR上的硬盤錄像文件回放。
- 支持云臺控制,向上、向下、向左、向右、左上、右上、左下、右下方位移動,鏡頭放大縮小,光圈放大縮小,鏡頭聚焦放焦。
- 支持預置位信息的查詢、調用、添加、修改、刪除等操作。
- 自動目錄訂閱功能,通道上線下線都有對應的信號通知。
- 內置定時讀取通道信息機制,以保證通道信息是最新的,比如有些NVR是不斷更新的通道信息。
- 內置訂閱警情和位置移動功能,訂閱后各種警情事件比如運動目標檢測報警、入侵檢測報警、徘徊檢測報警等自動上報。
- 支持語音對講功能,可以直接在視頻窗體的懸浮條上單擊語音對講按鈕,再次單擊關閉對講,對講期間懸浮條常駐顯示。
- 支持設備布防撤防,布防后警情信息會主動上報。
- 國標服務同時支持udp和tcp方式,可選只監聽一種或者兩種都監聽,tcp方式自動處理粘包問題。
- 國標拉流同時支持udp、tcp被動、tcp主動三種方式,每個通道都可以自由選擇何種拉流方式。
- 內置拉流端口池,每次拉流從中取出一個,關閉流自動回收端口號,重復利用。
- 收流端口自動糾錯,自動跳過被占用的端口,不會出現端口占用導致收流失敗的情況。
- 支持三種取流方式自動檢測離線重連,檢測到離線后,自動重啟點播拉流整個流程。
- 錄像文件回放,上一個完成后自動切換到下一個繼續回放,直到所有回放完成。支持高達8倍速回放。
- 視頻播放自適應硬解碼,極低資源占用,實時性極好,帶懸浮條顯示視頻流信息,可以直接在懸浮條單擊按鈕保存錄像文件到本地。
- 支持幾千路國標消息交互并發,實時視頻流支持64路同時顯示,可以拓展更多路數。
- 支持阿里云等云服務器,可以分別設置內網監聽地址和外網訪問地址,一般云服務器上是監聽地址用內網,對外訪問用外網地址。
- 支持視頻分發,也就是推流,視頻通道打開后可以自動推流到流媒體服務器,其他需要的地方拉流即可,支持rtsp、rtmp、hls、webrtc等方式拉流。
- 實時預覽和錄像回放都支持推流,推流支持疊加文字和圖片水印以及各種ffmpeg支持的濾鏡效果,支持多個水印同時疊加。
- 同時支持gb28181-2011、gb28181-2016、gb28181-2022以及后續可能的所有協議版本。
- SIP解析和交互采用純Qt底層代碼實現,udp/tcp通信交互,祖傳原創代碼解析,不依賴任何第三方。
- 代碼量少,gb28181交互部分共幾千行代碼,注釋詳細,接口友好,使用極其簡單,提供非常詳細的使用示例。
- 支持海康、大華、宇視、華為、天地偉業等所有國標設備,包括一些沒有ssrc的設備。
- 支持所有Qt版本和編譯器以及操作系統,包括但不限于win、linux、mac、android、嵌入式linux、樹莓派香橙派、國產os等。
五、相關代碼
#include "frmvideoplayback.h"
#include "ui_frmvideoplayback.h"
#include "qthelper.h"
#include "videoutil.h"
#include "gb28181server.h"
#include "gb28181helper.h"frmVideoPlayback::frmVideoPlayback(QWidget *parent) : QWidget(parent), ui(new Ui::frmVideoPlayback)
{ui->setupUi(this);this->initForm();this->initConfig();
}frmVideoPlayback::~frmVideoPlayback()
{delete ui;
}void frmVideoPlayback::closeAll()
{this->setId("", "");ui->listWidget->clear();ui->btnStop->click();
}void frmVideoPlayback::setServer(GB28181Server *server)
{this->server = server;ui->gb28181Widget->setServer(server);
}void frmVideoPlayback::setId(const QString &deviceId, const QString &channelId)
{this->deviceId = deviceId;this->channelId = channelId;
}void frmVideoPlayback::initForm()
{server = NULL;ui->sliderPosition->setRange(0, 0);ui->gb28181Widget->setBgText("視頻回放");ui->gb28181Widget->setProperty("onSync", AppConfig::RecordOnSync);connect(ui->btnPlay, SIGNAL(clicked(bool)), this, SLOT(playControl()));connect(ui->btnStop, SIGNAL(clicked(bool)), this, SLOT(playControl()));connect(ui->sliderPosition, SIGNAL(clicked()), this, SLOT(playControl()));connect(ui->cboxSpeed, SIGNAL(currentIndexChanged(int)), this, SLOT(playControl()));connect(ui->gb28181Widget, SIGNAL(sig_receivePlayStart(int)), this, SLOT(receivePlayStart(int)));connect(ui->gb28181Widget, SIGNAL(sig_receivePlayFinsh()), this, SLOT(receivePlayFinsh()));//進度定時器timer = new QTimer(this);connect(timer, SIGNAL(timeout()), this, SLOT(setPosition()));timer->setInterval(300);
}void frmVideoPlayback::initConfig()
{//ui->cboxSpeed->setEnabled(false);VideoUtil::loadSpeed(ui->cboxSpeed);ui->cboxSpeed->setCurrentIndex(ui->cboxSpeed->findData(AppConfig::RecordSpeed));connect(ui->cboxSpeed, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));ui->dateStart->setDateTime(QDateTime::fromString(AppConfig::RecordStart, "yyyy-MM-ddThh:mm:ss"));connect(ui->dateStart, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(saveConfig()));ui->dateEnd->setDateTime(QDateTime::fromString(AppConfig::RecordEnd, "yyyy-MM-ddThh:mm:ss"));connect(ui->dateEnd, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(saveConfig()));
}void frmVideoPlayback::saveConfig()
{AppConfig::RecordSpeed = ui->cboxSpeed->itemData(ui->cboxSpeed->currentIndex()).toString();AppConfig::RecordStart = ui->dateStart->dateTime().toString("yyyy-MM-ddThh:mm:ss");AppConfig::RecordEnd = ui->dateEnd->dateTime().toString("yyyy-MM-ddThh:mm:ss");AppConfig::writeConfig();
}void frmVideoPlayback::setPosition()
{qint64 pts = ui->gb28181Widget->getPts();VideoUtil::setPosition(ui->labPosition, ui->sliderPosition, pts * 100);
}void frmVideoPlayback::receivePlayStart(int)
{//取出時間QListWidgetItem *item = ui->listWidget->currentItem();QString startTime = item->data(Qt::UserRole + 1).toString();QString endTime = item->data(Qt::UserRole + 2).toString();//計算時長qint64 duration = GB28181Helper::getDuration(startTime, endTime) * 1000;VideoUtil::setDuration(ui->labDuration, ui->sliderPosition, duration);
}void frmVideoPlayback::receivePlayFinsh()
{timer->stop();ui->btnPlay->setText("暫停");VideoUtil::resetDuration(ui->labDuration, ui->labPosition, ui->sliderPosition);//暫停期間不用繼續if (ui->btnPlay->text() == "播放") {return;}//如果還有下一個自動觸發雙擊播放/過濾下剛剛關閉觸發的播放結束int row = ui->listWidget->currentRow();qint64 offset = lastTime.msecsTo(QDateTime::currentDateTime());if (offset > 1000 && row < ui->listWidget->count() - 1) {ui->listWidget->setCurrentRow(row + 1);on_listWidget_itemDoubleClicked(ui->listWidget->currentItem());}
}void frmVideoPlayback::playControl()
{QString ssrc = ui->gb28181Widget->getSsrcVideo();if (!server || ssrc.isEmpty()) {return;}QObject *obj = sender();if (obj == ui->btnPlay) {if (ui->btnPlay->text() == "暫停") {ui->btnPlay->setText("播放");server->playControl(deviceId, channelId, PlayControl_Pause, 0, ssrc);} else {ui->btnPlay->setText("暫停");server->playControl(deviceId, channelId, PlayControl_Play, 0, ssrc);}} else if (obj == ui->btnStop) {lastTime = QDateTime::currentDateTime();ui->gb28181Widget->stop();} else if (obj == ui->sliderPosition) {timer->stop();timer->start();ui->btnPlay->setText("暫停");qint64 sec = ui->sliderPosition->value() / 1000;server->playControl(deviceId, channelId, PlayControl_Position, sec);} else if (obj == ui->cboxSpeed) {float speed = ui->cboxSpeed->itemData(ui->cboxSpeed->currentIndex()).toFloat();server->playControl(deviceId, channelId, PlayControl_Scale, speed, ssrc);}
}void frmVideoPlayback::receiveStatus(GB28181Status status)
{if (status.deviceId != deviceId || status.channelId != channelId || status.notifyType != 121) {return;}//不是當前窗體產生的不用處理if (ui->gb28181Widget->getSsrcVideo() == status.ssrc) {ui->gb28181Widget->stop();}
}void frmVideoPlayback::receiveRecord(const QList<GB28181Record> &records)
{if (!this->isVisible()) {return;}foreach (GB28181Record record, records) {QString startTime = record.startTime;QString endTime = record.endTime;QString date = startTime.mid(0, 10);QString start = startTime.mid(11, 5);QString end = endTime.mid(11, 5);QListWidgetItem *item = new QListWidgetItem;item->setData(Qt::UserRole + 1, startTime);item->setData(Qt::UserRole + 2, endTime);item->setText(QString("%0 %1 - %2").arg(date).arg(start).arg(end));ui->listWidget->addItem(item);}
}void frmVideoPlayback::on_btnQueryRecord_clicked()
{ui->listWidget->clear();QDateTime dateStart = ui->dateStart->dateTime();QDateTime dateEnd = ui->dateEnd->dateTime();if (dateStart >= dateEnd) {QtHelper::showMessageBoxError("開始時間必須小于結束時間, 請重新選擇!");return;}server->queryRecord(deviceId, channelId, dateStart, dateEnd);
}void frmVideoPlayback::on_listWidget_itemDoubleClicked(QListWidgetItem *item)
{//取出時間QString startTime = item->data(Qt::UserRole + 1).toString();QString endTime = item->data(Qt::UserRole + 2).toString();//停止播放lastTime = QDateTime::currentDateTime();ui->gb28181Widget->stop();qApp->processEvents();timer->start();//啟動播放ui->gb28181Widget->initPara(AppConfig::ScaleMode, AppConfig::VideoMode, AppConfig::VideoCore, AppConfig::DecodeType, AppConfig::Hardware, AppConfig::ReadTimeout, false, false);ui->gb28181Widget->setPara(AppConfig::RecordSpeed.toFloat(), AppConfig::RecordProfile, (TransmitMode)AppConfig::TransmitMode, AppConfig::ServerIp, AppConfig::RecordPush, GB28181Widget::PlayType_Playback);ui->gb28181Widget->setTime(startTime, endTime);ui->gb28181Widget->openVideo(deviceId, channelId);
}