首页 > 其他分享 >Qt音视频开发41-文件推流(支持网页和播放器播放并切换进度)

Qt音视频开发41-文件推流(支持网页和播放器播放并切换进度)

时间:2023-04-27 09:24:02浏览次数:47  
标签:文件 return Qt 音视频 41 endPos startPos 推流 data

一、前言

本功能最初也是有一些人提过类似的需求,就是能不能将本地的音视频文件,通过纯Qt程序推流出去,然后用户可以直接在网页上播放,也可以用各种播放器播放,然后还可以任意切换播放进度,其实说白了就是个文件服务器,用户通过网络地址访问以后,告诉对方当前是媒体文件就会自动播放,是其他文件则可以开启下载,很多视频网站最初也是按照这个思路来设计,当然缺点很明显,那就是无法防止用户下载,毕竟这个本来就是当做文件发给用户的,无所谓保密的需求,话说现在的无论哪一种视频网站,只要能播放,用户就能通过各种手段录制下来的,也是无法规避这个问题。

无论网络协议如何发展,都离不开最底层的两种协议,tcp/udp通信,http也是建立在这两种协议基础上,然后又在http基础上衍生了众多的协议,总之,最基础的tcp/udp几十年都没变过,现在音视频发展这么迅速,衍生的各种rtmp/rtsp/hsl/webrtc啥的,最终底层还是基于tcp/udp通信,明白了这个道理,文件推流理论上基于tcp就可以实现。音视频文件在普通文件服务的基础上还多了个范围的参数Accept-Ranges: bytes/Content-Range,就是用户单击了进度后告诉服务这边当前要切换到哪个字节位置,这样就可以任意跳转播放进度。

二、效果图



三、体验地址

  1. 国内站点:https://gitee.com/feiyangqingyun
  2. 国际站点:https://github.com/feiyangqingyun
  3. 个人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
  4. 体验地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取码:01jf 文件名:bin_video_push。

四、相关代码

void FilePushClient::readData()
{
    //GET /后缀 HTTP/1.1
    //Host: 192.168.0.110:6908
    //Connection: keep-alive (一般网页请求是keep-alive/其他都是close)
    //Upgrade-Insecure-Requests: 1
    //User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
    //Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
    //Accept-Encoding: gzip, deflate
    //Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

    QByteArray data = tcpSocket->readAll();
    buffer.append(data);

    //超过了长度说明数据是垃圾数据
    if (buffer.size() > 1000) {
        buffer.clear();
        return;
    }

    //末尾必须是两个回车换行
    if (!buffer.endsWith("\r\n\r\n")) {
        return;
    }

    //解析请求(解析失败则不用继续)
    QHttpParser parser;
    bool ok = parser.parserRequest(buffer);
    emit receiveData(buffer);
    buffer.clear();
    if (!ok) {
        quit();
        return;
    }

    //不是对应的方法
    if (parser.method() != "GET") {
        quit();
        return;
    }

    //取出后缀地址(如果是请求图标则不用继续)
    QString url = parser.url();
    if (!url.startsWith("/") || url.startsWith("/favicon.ico")) {
        return;
    }

    //根据请求中的hash值查找文件
    QString hash = url.mid(1, url.length());
    FilePushServer *server = (FilePushServer *)this->parent();
    QString fileName = server->findFile(hash);
    if (!this->setFile(fileName)) {
        quit();
        return;
    }

    QString range = parser.headerValue("Range");
    if (range.isEmpty()) {
        this->writeData200(0);
        return;
    }

    //Range: bytes=0- / bytes=-1024 / bytes=0-1024
    QStringList list = range.split("=");
    if (list.count() != 2) {
        quit();
        return;
    }

    //取出进度范围
    range = list[1];
    range.replace(" ", "");
    list.clear();
    list = range.split("-");

    //测试下来发现基本上都是 x- 的情况
    qint64 startPos, endPos;
    if (range.startsWith("-")) {
        endPos = fileSize - 1;
        startPos = endPos - list.at(0).toInt();
    } else if (range.endsWith("-")) {
        startPos = list.at(0).toInt();
        endPos = fileSize - 1;
    } else {
        startPos = list.at(0).toInt();
        endPos = list.at(1).toInt();
    }

    this->writeData206(startPos, endPos);
}

void FilePushClient::writeData(qint64 bytes)
{
    writeByteCount -= bytes;
    if (tcpSocket && writeByteCount > 0) {
        qint64 size = 512 * 1024;
        size = tcpSocket->write(file->read(size));
        //qDebug() << TIMEMS << "writeData" << size;
    }
}

QByteArray FilePushClient::getHeadData(const QString &flag, qint64 startPos, qint64 endPos, qint64 bufferSize)
{
    QStringList list;
    list << flag;
    list << "Server: QQ_517216493 WX_feiyangqingyun";
    list << "Cache-control: no-cache";
    list << "Pragma: no-cache";
    list << "Connection: close";
    list << "Accept-Ranges: bytes";
    list << "Access-Control-Allow-Origin: *";
    list << QString("Content-Type: %1").arg(fileType);
    list << QString("Content-Length: %1").arg(bufferSize);
    if (playMode == 1) {
        list << QString("Content-Disposition: attachment;filename=%1").arg(fileName);
    }
    list << QString("Content-Range: bytes %1-%2/%3").arg(startPos).arg(endPos).arg(fileSize);
    //末尾必须加个回车换行
    list << "\r\n";

    QString data = list.join("\r\n");
    return data.toUtf8();
}

void FilePushClient::writeData200(qint64 startPos)
{
    if (!file->isOpen()) {
        return;
    }

    if (startPos >= fileSize) {
        return;
    }

    //文件切换到对应位置
    file->seek(startPos);
    qint64 endPos = fileSize - 1;
    qint64 bufferSize = fileSize - startPos;
    QByteArray data = getHeadData("HTTP/1.1 200 OK", startPos, endPos, bufferSize);

    //计算并发送数据
    writeByteCount = data.size() + (fileSize - startPos);
    tcpSocket->write(data);
    emit sendData(data);
    //qDebug() << TIMEMS << "writeData200";
}

void FilePushClient::writeData206(qint64 startPos, qint64 endPos)
{
    if (!file->isOpen()) {
        return;
    }

    if (startPos >= fileSize || startPos >= endPos) {
        return;
    }

    //文件切换到对应位置
    file->seek(startPos);
    qint64 bufferSize = endPos - startPos + 1;
    QByteArray data = getHeadData("HTTP/1.1 206 Partial Content", startPos, endPos, bufferSize);

    //计算并发送数据
    writeByteCount = data.size() + (fileSize - startPos);
    tcpSocket->write(data);
    emit sendData(data);
    //qDebug() << TIMEMS << "writeData206";
}

五、功能特点

5.1 文件推流

  1. 指定网卡和监听端口,接收网络请求推送音视频等各种文件。
  2. 实时统计显示每个文件对应的访问数量、总访问数量、不同IP地址访问数量。
  3. 可指定多种模式,0-直接播放、1-下载播放。
  4. 实时打印显示各种收发请求和应答数据。
  5. 每个文件对应MD5加密的唯一标识符,用于请求地址后缀区分访问哪个文件。
  6. 支持各种浏览器(谷歌chromium/微软edge/火狐firefox等)、各种播放器(vlc/mpv/ffplay/potplayer/mpchc等)打开请求。
  7. 播放过程中可以任意切换播放进度,支持倍速播放。
  8. 需要推流的文件名称历史记录自动存储和打开加载应用。
  9. 切换文件获取访问地址,自动拷贝地址到剪切板方便直接粘贴测试使用。
  10. 极低CPU占用,128路1080P同时推流不到1%CPU占用,异步发送数据机制。
  11. 纯QTcpSocket通信,不依赖流媒体服务程序,核心源码不到500行,注释详细,功能完整。
  12. 支持Qt4/Qt5/Qt6任意版本,支持任意系统(windows/linux/macos/android/嵌入式linux等)。

5.2 网络推流

  1. 支持各种本地视频文件和网络视频文件。
  2. 支持各种网络视频流,网络摄像头,协议包括rtsp、rtmp、http。
  3. 支持将本地摄像头设备推流,可指定分辨率和帧率等。
  4. 支持将本地桌面推流,可指定屏幕区域和帧率等。
  5. 自动启动流媒体服务程序,默认mediamtx(原rtsp-simple-server),可选用srs、EasyDarwin、LiveQing、ZLMediaKit等。
  6. 可实时切换预览视频文件。
  7. 推流的清晰度和质量可调。
  8. 可动态添加文件、目录、地址。
  9. 视频文件自动循环推流,如果视频源是视频流,在掉线后会自动重连。
  10. 网络视频流自动重连,重连成功自动继续推流。
  11. 网络视频流实时性极高,延迟极低,延迟时间大概在100ms左右。
  12. 推流后除了用rtmp地址访问以外,还支持直接hls/webrtc访问,可以直接浏览器打开看实时画面。
  13. 支持Qt4/Qt5/Qt6任意版本,支持任意系统(windows/linux/macos/android/嵌入式linux等)。

标签:文件,return,Qt,音视频,41,endPos,startPos,推流,data
From: https://www.cnblogs.com/feiyangqingyun/p/17357989.html

相关文章

  • 音视频八股文(6)-- ffmpeg大体介绍和内存模型
    播放器框架常用音视频术语•容器/文件(Conainer/File):即特定格式的多媒体文件,比如mp4、flv、mkv等。•媒体流(Stream):表示时间轴上的一段连续数据,如一段声音数据、一段视频数据或一段字幕数据,可以是压缩的,也可以是非压缩的,压缩的数据需要关联特定的编解码器(有些码流音频他是纯PCM)......
  • Qt6.5配置Android开发环境最简单方法
    下载qt6.5时记得勾选Android。详细方法看我编译mysql那篇文章安装好后,打开qtcreater进入配置 首先需要配置jdk,网上方法很多不过多赘述,进入设备切换到Android页面,若配置好了jdk会显示jdk的位置,在这个页面我们只需要点击设置SDK即可联网下载所有的配置文件包括SDK、NDK以及......
  • qt 代码设置layout中的控件的比例,以水平布局为例
    voidDisplayPathFilename::mainlayout(){m_hboxlayout->addWidget(m_filenamelabel);m_filenamelabel->setText("配置文件:");m_hboxlayout->addWidget(m_filenamelineedit);m_hboxlayout->addWidget(m_displaypathlabel);m_dis......
  • Qt+MySql开发笔记:Qt5.9.3的msvc2017x64版本编译MySql8.0.16版本驱动并Demo连接数据库
    前言  mysql驱动版本msvc2015x32版本调好,mysql的mingw32版本的驱动上一个版本编译并测试好,有些三方库最低支持vs2017,所以只能使用msvc2017x64,基于Qt5.9.3,于是本篇编译mysql驱动的msvc2017x64版本,满足当前的特定需求,这次过程有点费劲,可能是Qt的版本低于Qt5.12,继续无保留分享......
  • net::ERR_FAILED 413
    后台收不到post请求,前端报错413具体情况如下: 开始以为是跨域又有问题,进一步发现是上传的图片文件过大。Node.js环境中koa框架使用还不熟练。参考笔记-node.jskoa框架。请求体过大报413错误-简书(jianshu.com)引入koa-bodyparser 挂载配置,将文件大小设置为不超过10MB......
  • Yuzuki Lizard 全志V851S开发板 –移植 QT5.12.9教程
    移植QT5教程(此教程基于docker版V851S开发环境)dockerpullregistry.cn-hangzhou.aliyuncs.com/gloomyghost/yuzukilizard编译依赖apt-getinstallrepogitgcc-arm-linux-gnueabihfu-boot-toolsdevice-tree-compilermtools\partedlibudev-devlibusb-1.0-0-devpython......
  • [LeetCode] 2418. Sort the People
    Youaregivenanarrayofstrings names,andanarray heights thatconsistsof distinct positiveintegers.Botharraysareoflength n.Foreachindex i, names[i] and heights[i] denotethenameandheightofthe ith person.Return names sorted......
  • 音视频八股文(5)--SDL音视频渲染实战。会使用就行,不需要深究。
    01-SDL子系统SDL将功能分成下列数个子系统(subsystem):◼SDL_INIT_TIMER:定时器◼SDL_INIT_AUDIO:音频◼SDL_INIT_VIDEO:视频◼SDL_INIT_JOYSTICK:摇杆◼SDL_INIT_HAPTIC:触摸屏◼SDL_INIT_GAMECONTROLLER:游戏控制器◼SDL_INIT_EVENTS:事件◼SDL_INIT_EVERYTHING:包含上述所......
  • 音视频八股文(5)--SDL音视频渲染实战。会使用就行,不需要深究。
    01-SDL子系统SDL将功能分成下列数个子系统(subsystem):◼SDL_INIT_TIMER:定时器◼SDL_INIT_AUDIO:音频◼SDL_INIT_VIDEO:视频◼SDL_INIT_JOYSTICK:摇杆◼SDL_INIT_HAPTIC:触摸屏◼SDL_INIT_GAMECONTROLLER:游戏控制器◼SDL_INIT_EVENTS:事件◼SDL_INIT_EVERYTHING:包含上述......
  • ASEMI代理ADI亚德诺ADG5412BRUZ-REEL7车规级芯片
    编辑-ZADG5412BRUZ-REEL7芯片参数:型号:ADG5412BRUZ-REEL7开态电阻:9.8Ω电源断开漏电流:±0.05nA输入高电压:2V输入低电压:0.8V输入电流:0.002μA数字输入电容:2.5pF−3dB带宽:167MHzVDDtoGND:−0.3Vto+48VVSStoGND:+0.3Vto−48V工作温度范围:−40°Cto+125°C......