基于Qt的海康威视SDK二次开发-摄像头登陆、预览和抓图

最近有个项目涉及海康威视的摄像头部分,需要在服务器端自动定时抓图,由于服务器端采用的是Windows系统,不熟Windows的api,所以直接采用Qt来编写。那么摄像头的激活配置什么的就不再介绍了,直接进入正题。

先下载海康的SDK,https://www.hikvision.com/cn/download_61.html,我的电脑系统是64位的,QT版本5.10.0,QT Creator是32位的,编译器是mingw32,介于编译器是32位,同时32位的程序能够在32、64位的系统下运行,但是64位的就只能在64位系统下运行,因此为了后期的兼容性,我下载了32位的SDK,至于能不能下载64位的SDK,可以自行尝试。

其次设置硬件设备,网络摄像头相当于一个服务器,我们的程序要访问它并获取视频数据,因此这个摄像头无论在内网还是外网,只要能访问到就行,最简单的方式就是ping它的IP,能通就行,我的IP是192.168.10.102,然后是服务端口,服务端口可以自行网页登陆摄像头查看,我这里是默认值,8000,然后是账号和密码,账号分为两种,管理员账号admin和普通账号,管理员账号的密码就是激活的时候让输入的密码,普通账号是激活后登陆摄像头自行设置的,我这里还是默认的admin和激活时候设置的密码。硬件环境大致就是这个样子。

然后新建一个Qt工程,我选择是继承于QWidget的类,当然其他基类也行,接着从下载的sdk里将头文件文件夹和库文件文件夹都拷到Qt工程目录下,分别修改为英文,我这里是include和libs,注意这里修改的名字应当和程序中对应;接下来是将库添加到QT工程中,使其编译时能够加载,库目录中有lib和dll,这两个都是库,这里插嘴说一下二者的区别,当Windows下一个工程编译成库时,可以有两种方式,第一种是静态库,第二种是动态库,静态库在编译时读取,动态库在运行时读取,生成静态库时只有lib文件,里边存放的就是函数的实现,生成动态库时,lib和dll文件都有,其中lib中没有函数的实现代码,只存放了该实现代码位于哪个dll中,dll中存放函数的实现代码;我们在调用静态库时,代码在链接阶段,将去对应lib中寻找实现代码,并进行链接,结束后,lib就没用了;而调用动态库时,代码在链接阶段也会去lib中寻找,不同的是,它只会留下标记,标识去哪里找运行代码,而不实际将dll中的实现链接进程序里,因此程序运行时不需要lib,但是必须有dll。言归正传,海康威视的SDK是动态库,我们需要指定lib文件的位置,运行时将dll文件放置在程序运行目录下即可,在QT中指定lib文件的位置是修改pro文件,添加如下代码:

LIBS +=-LH:/QTproject/HKDemo/HKDemo/libs -lHCCore -lHCNetSDK -lPlayCtrl
LIBS +=-LH:/QTproject/HKDemo/HKDemo/libs/HCNetSDKCom -lHCAlarm -lHCGeneralCfgMgr -lHCPreview

和Linux系统的加库方法非常像,-L表示库的搜索路径,-l表示链接哪个库,注意这里的路径要写全,我试过相对路径,没有成功,至此编译时的库加入到了QT工程中。

接下来要做的就是写代码了,我们可以根据海康威视提供的文档进行编写,其文档位于开发文档目录下,我使用的是设备网络SDK使用手册.chm,我们可以在里边看到使用流程,及一些接口的依赖关系:

整个大的框架就是初始化,注册,预览,停止预览,注销,释放资源,初始化SDK和释放SDK资源不必多说,是sdk的基础操作,然后注册就是登陆摄像头,注销就是退出登陆,注意抓图分为两种,预览抓图和设备抓图,预览抓图必须先开启预览,而设备抓图不用,因为我是做服务器端程序用的,就使用了设备抓图,即不需要预览就可以抓图。

  • 初始化SDK和释放SDK资源

 

 

SDK中初始化资源函数为NET_DVR_Init(),资源释放函数为NET_DVR_Cleanup()。

由于这是SDK的基础操作,我们在窗体的构造函数执行初始化SDK的操作,在析构函数中执行释放SDK资源的操作,初始化SDK和释放SDK的代码如下:

bool Widget::initSDK()
{
    bool isok = NET_DVR_Init();
    if(isok == false)
    {
        qDebug()<< "NET_DVR_Init error;error number is " <<NET_DVR_GetLastError();
        QMessageBox::warning(this,"error","NET_DVR_Init error;error number is "+QString::number(NET_DVR_GetLastError()));
        return isok;
    }
    //设置连接时间与重连时间
    NET_DVR_SetConnectTime(2000, 1);
    NET_DVR_SetReconnect(10000, true);
    return isok;
}

bool Widget::uninitSDK()
{
    bool isok = NET_DVR_Cleanup();
    if(isok == false)
    {
        qDebug()<< "NET_DVR_Cleanup error;error number is " <<NET_DVR_GetLastError();
        QMessageBox::warning(this,"error","NET_DVR_Cleanup error;error number "+QString::number(NET_DVR_GetLastError()));
        return isok;
    }
    return isok;
}
  • 登录和退出登录

其余接口不再累述,自己查即可,这里我用的是NET_DVR_Login_V30函数和NET_DVR_Logout,代码如下:

void Widget::OnClickedLogin()
{
    NET_DVR_DEVICEINFO_V30 DeviceInfoTmp;
    userID=NET_DVR_Login_V30("192.168.10.102",8000,"admin","1234536asd",&DeviceInfoTmp);//参数依次为IP地址、服务端口、账号、密码,最后一个参数是为了获得硬件信息的
    if(userID<0)
    {
        qDebug() << "NET_DVR_Login_V30 error;" << "error number is " << NET_DVR_GetLastError();
        QMessageBox::warning(this,"error","NET_DVR_Login_V30 error;error number "+QString::number(NET_DVR_GetLastError()));
        return;
    }
    qDebug()<<"Login Success,userID:" << userID<<endl;
}

void Widget::OnClickedLogout()
{
    if(userID!=-1)
    {
        if(NET_DVR_Logout(userID)==false)
        {
            qDebug() << "NET_DVR_Logout error;" << "error number is " << NET_DVR_GetLastError();
            QMessageBox::warning(this,"error","NET_DVR_Logout error;error number "+QString::number(NET_DVR_GetLastError()));
            return;
        }
        userID=-1;
        qDebug() <<"Logout Success!"<<endl;
    }
}
  • 预览和停止预览

预览函数需要获得窗体句柄,并且是Windows api中定义的句柄,本质上来讲,QT写出的窗体也是windows窗体,我们这里直接定义一个label控件,控件中有个成员函数是专门获得windows下的窗体句柄的,传入该句柄后,函数就会自动向窗体传递图像信息并显示,不需我们的任何操作,同时也不会阻塞在这个函数,应该是直接利用了windows api的消息机制,代码如下:

void Widget::OnClickedPreview()
{
    if(userID==-1)
    {
        qDebug() <<"Need Login!"<<endl;
        QMessageBox::warning(this,"error","Need Login!");
        return;
    }
    HWND hWnd = (HWND)ui->label->winId();//HWND是windows api的窗体句柄类型
    NET_DVR_PREVIEWINFO struPlayInfo;
    previewID = play(hWnd,struPlayInfo);
    if(previewID==-1)
    {
        return;
    }
    qDebug()<<"Preview Success!" << userID<<endl;
}

void Widget::OnClickedStopPreview()
{
    if(previewID!=-1)
    {
        if(NET_DVR_StopRealPlay(previewID)==false)
        {
            qDebug() << "NET_DVR_StopRealPlay error;" << "error number is " << NET_DVR_GetLastError();
            QMessageBox::warning(this,"error","NET_DVR_StopRealPlay error;error number "+QString::number(NET_DVR_GetLastError()));
            return;
        }
        previewID=-1;
        qDebug() <<"Stop Preview Success!"<<endl;
    }
}
  • 抓图

这里使用的是设备抓图,即可以在登录后直接抓图,不需要预览,但是这个函数只能获取jpeg图像,会损失精度,可以采用预览抓图函数,其可以设置获取BMP图像还是jpeg图像。注意文件路径必须包括文件名字,还有Windows下的要加双斜杠,另外文件路径中的文件夹应当在该函数之前创建,代码如下:

void Widget::OnClickedCapture()
{

    if(userID!=-1)
    {
        NET_DVR_JPEGPARA IpJpegPara2;
        IpJpegPara2.wPicQuality=0;
        IpJpegPara2.wPicSize=0xff;

        QDateTime current_date_time =QDateTime::currentDateTime();
        QString current_date =current_date_time.toString("yyyy-MM-dd_hh-mm-ss_zzz");
        current_date="C:\\Picture\\"+current_date+".jpg";
        char*  fileName;
        QByteArray ba = current_date.toLatin1(); // must
        fileName=ba.data();


        if(NET_DVR_CaptureJPEGPicture(userID,1,&IpJpegPara2,fileName)==false)
        {
            qDebug() << "NET_DVR_CaptureJPEGPicture error;" << "error number is " << NET_DVR_GetLastError();
            QMessageBox::warning(this,"error","NET_DVR_CaptureJPEGPicture error;error number "+QString::number(NET_DVR_GetLastError()));
            return;
        }
        qDebug() <<"Capture Success!"<<endl;
    }
}

整体流程就是这个样子,下面给出完整代码。

  • main.cpp
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}
  • widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QDateTime>
#include "include/HCNetSDK.h"
#include <windows.h>
#include <QMessageBox>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    long play(HWND hWnd,NET_DVR_PREVIEWINFO struPlayInfo);
    bool initSDK();
    bool uninitSDK();
public slots:
    void OnClickedLogin();
    void OnClickedLogout();
    void OnClickedPreview();
    void OnClickedStopPreview();
    void OnClickedCapture();
private:
    Ui::Widget *ui;
    long userID;
    long previewID;
};

#endif // WIDGET_H
  • widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    userID=-1;
    previewID=-1;
    connect(ui->LoginButton,&QPushButton::clicked,this,&Widget::OnClickedLogin);
    connect(ui->LogoutButton,&QPushButton::clicked,this,&Widget::OnClickedLogout);
    connect(ui->PreviewButton,&QPushButton::clicked,this,&Widget::OnClickedPreview);
    connect(ui->StopPreviewButton,&QPushButton::clicked,this,&Widget::OnClickedStopPreview);
    connect(ui->CaptureButton,&QPushButton::clicked,this,&Widget::OnClickedCapture);
    if(initSDK())
        qDebug()<<"SDK init Success!"<<endl;
}

Widget::~Widget()
{
    if(uninitSDK())
        qDebug()<<"SDK uninit Success!"<<endl;
    delete ui;
}

long Widget::play(HWND hWnd, NET_DVR_PREVIEWINFO struPlayInfo)
{
    struPlayInfo={0};
    struPlayInfo.hPlayWnd = hWnd;//需要 SDK 解码时句柄设为有效值,仅取流不解码时可设为空
    struPlayInfo.lChannel = 1;//预览通道号
    struPlayInfo.dwStreamType = 0;//码流类型:0-主码流,1-子码流,2-三码流,3-虚拟码流,以此类推
    struPlayInfo.dwLinkMode = 0;//0- TCP 方式,1- UDP 方式,2- 多播方式,3- RTP 方式,4-RTP/RTSP,5-RSTP/HTTP
    struPlayInfo.bBlocked = 1;//0- 非阻塞取流,1- 阻塞取流

    long IRealPlayHandle = NET_DVR_RealPlay_V40(userID,&struPlayInfo,NULL,NULL);

    if(IRealPlayHandle <0)
    {
        qDebug() << "NET_DVR_RealPlay_V40 error;error number " <<NET_DVR_GetLastError();
        QMessageBox::warning(this,"error","NET_DVR_RealPlay_V40 error;error number "+QString::number(NET_DVR_GetLastError()));
        NET_DVR_Logout(userID);
        userID=-1;
        return -1;
    }

    return IRealPlayHandle;
}

bool Widget::initSDK()
{
    bool isok = NET_DVR_Init();
    if(isok == false)
    {
        qDebug()<< "NET_DVR_Init error;error number is " <<NET_DVR_GetLastError();
        QMessageBox::warning(this,"error","NET_DVR_Init error;error number is "+QString::number(NET_DVR_GetLastError()));
        return isok;
    }
    //设置连接时间与重连时间
    NET_DVR_SetConnectTime(2000, 1);
    NET_DVR_SetReconnect(10000, true);
    return isok;
}

bool Widget::uninitSDK()
{
    bool isok = NET_DVR_Cleanup();
    if(isok == false)
    {
        qDebug()<< "NET_DVR_Cleanup error;error number is " <<NET_DVR_GetLastError();
        QMessageBox::warning(this,"error","NET_DVR_Cleanup error;error number "+QString::number(NET_DVR_GetLastError()));
        return isok;
    }
    return isok;
}

void Widget::OnClickedLogin()
{
    NET_DVR_DEVICEINFO_V30 DeviceInfoTmp;
    userID=NET_DVR_Login_V30("192.168.10.102",8000,"admin","5456123asdas",&DeviceInfoTmp);
    if(userID<0)
    {
        qDebug() << "NET_DVR_Login_V30 error;" << "error number is " << NET_DVR_GetLastError();
        QMessageBox::warning(this,"error","NET_DVR_Login_V30 error;error number "+QString::number(NET_DVR_GetLastError()));
        return;
    }
    qDebug()<<"Login Success,userID:" << userID<<endl;
}

void Widget::OnClickedLogout()
{
    if(userID!=-1)
    {
        if(NET_DVR_Logout(userID)==false)
        {
            qDebug() << "NET_DVR_Logout error;" << "error number is " << NET_DVR_GetLastError();
            QMessageBox::warning(this,"error","NET_DVR_Logout error;error number "+QString::number(NET_DVR_GetLastError()));
            return;
        }
        userID=-1;
        qDebug() <<"Logout Success!"<<endl;
    }
}

void Widget::OnClickedPreview()
{
    if(userID==-1)
    {
        qDebug() <<"Need Login!"<<endl;
        QMessageBox::warning(this,"error","Need Login!");
        return;
    }
    HWND hWnd = (HWND)ui->label->winId();
    NET_DVR_PREVIEWINFO struPlayInfo;
    previewID = play(hWnd,struPlayInfo);
    if(previewID==-1)
    {
        return;
    }
    qDebug()<<"Preview Success!" << userID<<endl;
}

void Widget::OnClickedStopPreview()
{
    if(previewID!=-1)
    {
        if(NET_DVR_StopRealPlay(previewID)==false)
        {
            qDebug() << "NET_DVR_StopRealPlay error;" << "error number is " << NET_DVR_GetLastError();
            QMessageBox::warning(this,"error","NET_DVR_StopRealPlay error;error number "+QString::number(NET_DVR_GetLastError()));
            return;
        }
        previewID=-1;
        qDebug() <<"Stop Preview Success!"<<endl;
    }
}

void Widget::OnClickedCapture()
{

    if(userID!=-1)
    {
        NET_DVR_JPEGPARA IpJpegPara2;
        IpJpegPara2.wPicQuality=0;
        IpJpegPara2.wPicSize=0xff;

        QDateTime current_date_time =QDateTime::currentDateTime();
        QString current_date =current_date_time.toString("yyyy-MM-dd_hh-mm-ss_zzz");
        current_date="C:\\Picture\\"+current_date+".jpg";
        char*  fileName;
        QByteArray ba = current_date.toLatin1(); // must
        fileName=ba.data();


        if(NET_DVR_CaptureJPEGPicture(userID,1,&IpJpegPara2,fileName)==false)
        {
            qDebug() << "NET_DVR_CaptureJPEGPicture error;" << "error number is " << NET_DVR_GetLastError();
            QMessageBox::warning(this,"error","NET_DVR_CaptureJPEGPicture error;error number "+QString::number(NET_DVR_GetLastError()));
            return;
        }
        qDebug() <<"Capture Success!"<<endl;
    }
}
  • 发布应用

发布应用应当以release模式编译,然后使用windeployqt 工具进行qt依赖项的导出,接着要将海康威视的dll也放入可执行文件目录下,这里为简单起见,直接将下载的海康威视的sdk中的库文件中的所有文件、目录复制到可执行文件目录下,如下图所示:

仍无法实现的,可以下载我打包好的,包括源代码和可执行文件及其依赖项。发布的应用里直接写死了IP和端口,可以在源码中修改为窗体输入。https://download.csdn.net/download/cx296649890/11574696

  • 23
    点赞
  • 154
    收藏
    觉得还不错? 一键收藏
  • 47
    评论
内含SDK、开发文档 及Demo示例(C++、C#、Java) 设备网络SDK是基于设备私有网络通信协议开发的,为后端设备(嵌入式网络硬盘录像机、视频服务器)、前端设备(网络摄像机、网络球机、IP模块)等产品服务的配套模块,用于远程访问和控制设备软件的二次开发。 适用于但不仅限于以下产品型号: 1.编解码设备 DVR:DS-9100、DS-8100、DS-8000-S、DS-8800、DS-7800、DS-7300、DS-7200、DS-7100、DS-7000等系列,包括-ST、-SH、-SE、-SN、-RT、-RH、-XT等; NVR:DS-96000、DS-9600、DS-9500、DS-8600、DS-7900、DS-7800、DS-7700、DS-7600、DS-7100等系列,包括-I、-F、-K、-E、-H、-ST、-XT、-SN、-SE、-SNH、-SHT、-S、-SH、-RT等; XVR:DS-9000HQH-SH、DS-8100HQH(/HGH)-SH、DS-8000HQH-SH、DS-7300HQH(/HGH)-SH、DS-7200HQH(/HGH)-SH、DS-8800HQH(/HGH)(/HUH)-SH(/Fx)、DS-7900HQH(/HGH)(/HUH)-SH(/Fx)、DS-7800HQH(/HGH)(/HUH)-SH(/Ex/Fx)、DS-7100HGH-E1(/F1)等; HDVR(混合型DVR):DS-9000、DS-8000-ST、DS-7600H-ST/-S系列等; 编码器:DS-6700、DS-6600、DS-6500(-JX)、DS-6100、DS-6401HFH系列视频服务器、DS-6000系列编/解码器等; 解码器:DS-6300D(-JX)、DS-6400HD(-JX/-T)、DS-6500D(-T)等 2. 网络摄像机, 网络球机 网络摄像机:标清、高清、红外、热成像、鱼眼等,如DS-2CD7xx、DS-2CD71xx、DS-2CD72xx、DS-2CD8xx、DS-2CD81xx、DS-2CD82xx、DS-2CD84xx、DS-2CD83xx、DS-2CD11xx、DS-2CD12xx、DS-2CD13xx、DS-2CD20xx、DS-2CD21xx、DS-2CD22xx、DS-2CD23xx、DS-2CD24xx、DS-2CD25xx、DS-2CD26xx、DS-2CD27xx、DS-2CD28xx、DS-2CD29xx、DS-2CD2Axx、DS-2CD2Cxx、DS-2CD2Dxx、DS-2CD2Txx、DS-2CD2Qxx、DS-2CD30xx、DS-2CD31xx、DS-2CD32xx、DS-2CD33xx、DS-2CD34xx、DS-2CD39xx、DS-2CD3Txx、DS-2CD3Qxx、DS-2CD40xx、DS-2CD41xx、DS-2CD42xx、DS-2CD4Axx、DS-2CD62xx、DS-2CD63xx、DS-2CD65xx等 网络球机:标清、高清、红外等,如DS-2DF86xx、DS-2DF85xx、DS-2DF82xx、DS-2DF72xx、DS-2DF71xx、DS-2DE71xx、DS-2DE73xx、DS-2DE72xx、DS-2DM72xx、DS-2DM71xx、DS-2DF1-7xx、DS-2DF66xx、DS-2DF62xx、DS-2DF1-6xx、DS-2DE51xx、DS-2DE52xx、DS-2DE53xx、DS-2DM52xx、DS-2DF52xx、DS-2DC52xx、DS-2DC51xx、DS-2DF1-5xx、DS-2DE45xx、DS-2DE42xx、DS-2DE41xx、DS-2DF1-4xx、DS-2DM1-7xx、DS-2DM1-6xx、DS-2DM1-5xx等 一体化网络摄像机:DS-2ZCN3007、DS-2ZCN3006、DS-2DZ216MF、DS-2DZ2116、DS-2ZCN2006、DS-2ZCN2007、DS-2ZMN2007、DS-2ZMN2006等 3. 智能交通产品 出入口抓拍机:(i)DS-2CD95xx、(i)DS-2CD93xx、(i)DS-2CD92xx、(i)DS-2CD91xx、DS-2CD9xx、DS-TCGxxx、EVU-xxxx等 车位相机:DS-TCPxxx等 出入口控制机:DS-TMExxx等 诱导管理器:DS-TPMxxx等 4. 智能设备 行为分析、ATM防护、自动跟踪、客流量统计、人脸识别、智能交通事件、VQD视频质量诊断等 5. 其他IP设备 CVR、报警主机、门禁、可视对讲、LCD拼接屏、IP模块等
进行海康威视SDK二次开发的步骤如下: 1. 首先,您需要进入海康威视官网,下载最新版本的设备网络SDK。这个SDK包含了各种功能和接口,可以帮助您进行二次开发。您可以通过访问海康威视官网并在下载页面找到适合您系统的32位Windows版的SDK。 2. 下载完成后,您需要将SDK解压缩到您的开发环境中。确保您的开发环境已经配置好,并且可以访问到SDK所需的依赖库和文件。 3. 在进行SDK二次开发之前,您需要仔细阅读海康威视的开发文档。这些文档会提供给您SDK的详细说明和使用方法。特别是关于SDK接口的初始化和资源释放的部分,您需要特别注意。 4. 在开始编写代码之前,您可以先确定您的项目需求和目标。根据您的需求,选择适合的SDK接口进行开发。您可以使用SDK提供的各种功能,如视频流获取、图像处理、设备控制等。 5. 在编写代码时,您需要按照SDK文档提供的接口说明来调用相应的函数。在调用SDK接口之前,您需要进行初始化操作,以确保SDK能够正常工作。在完成操作之后,记得释放SDK所占用的资源,以免造成内存泄漏或其他问题。 6. 在开发过程中,您可能会遇到一些问题或困惑。您可以参考海康威视官方网站提供的开发者社区或技术支持渠道,寻求帮助和解答。 总结起来,进行海康威视SDK二次开发的关键步骤包括下载最新版本的设备网络SDK,阅读开发文档并了解SDK的初始化和资源释放操作,根据项目需求选择适合的功能和接口进行开发,编写代码并调用SDK接口,最后注意释放SDK所占用的资源。希望这些步骤能够帮助您进行海康威视SDK二次开发。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [基于海康威视SDK实现二次开发](https://blog.csdn.net/weixin_44738214/article/details/126168881)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [海康威视sdk二次开发包.zip](https://download.csdn.net/download/weixin_43297335/12288413)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 47
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值