Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Streaming audio file to a network camera
Forum Updated to NodeBB v4.3 + New Features

Streaming audio file to a network camera

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 4 Posters 552 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • JansiJ Offline
    JansiJ Offline
    Jansi
    wrote on last edited by
    #1

    Hi, I have a Doorbird doorbell and I am trying to use its API to play a sound. The request should look like this:

    POST /bha-api/audio-transmit.cgi HTTP/1.0\r\n
    Content-Type: audio/basic\r\n
    Content-Length: 9999999\r\n
    Connection: Keep-Alive\r\n
    Cache-Control: no-cache\r\n
    \r\n
    <AUDIO DATA>
    <AUDIO DATA>
    <AUDIO DATA>
    ...
    

    I am sending the sound file using QNetworkAccessManager like this:

    QNetworkRequest request(m_url);
    
    QFile *sound = new QFile(":/resources/test.wav");
    if(!sound->open(QIODevice::ReadOnly)) { }
    
    QByteArray bytes = sound->readAll();
    
    request.setHeader(QNetworkRequest::ContentTypeHeader, "audio/basic");
    request.setHeader(QNetworkRequest::ContentLengthHeader, "9999999");
    request.setRawHeader("Connection", "Keep-Alive");
    request.setRawHeader("Cache-Control", "no-cache");
    
    QNetworkReply *reply = m_networkManager->post(request, bytes);
    sound->setParent(reply);
    
    connect(reply, &QNetworkReply::finished, this, [=]() {
        if (reply->error() != QNetworkReply::NoError) {
            qDebug() << "Error: " + QString(reply->errorString());
        }
    
        QVariant statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute );
        qDebug() << "Status code: " + statusCode.toString();
    });
    

    There is no error and the returned status code is 200. The problem is I can hear only a very quick sound lasting less than a second.

    I think the problem lies in the fact that I am uploading the whole file at once while it is expected to be streamed in real-time (it should be a voice transmission).

    How do I stream the file as if it was live voice recording instead of uploading it all at once?

    aha_1980A Pablo J. RoginaP 2 Replies Last reply
    0
    • JansiJ Jansi

      Hi, I have a Doorbird doorbell and I am trying to use its API to play a sound. The request should look like this:

      POST /bha-api/audio-transmit.cgi HTTP/1.0\r\n
      Content-Type: audio/basic\r\n
      Content-Length: 9999999\r\n
      Connection: Keep-Alive\r\n
      Cache-Control: no-cache\r\n
      \r\n
      <AUDIO DATA>
      <AUDIO DATA>
      <AUDIO DATA>
      ...
      

      I am sending the sound file using QNetworkAccessManager like this:

      QNetworkRequest request(m_url);
      
      QFile *sound = new QFile(":/resources/test.wav");
      if(!sound->open(QIODevice::ReadOnly)) { }
      
      QByteArray bytes = sound->readAll();
      
      request.setHeader(QNetworkRequest::ContentTypeHeader, "audio/basic");
      request.setHeader(QNetworkRequest::ContentLengthHeader, "9999999");
      request.setRawHeader("Connection", "Keep-Alive");
      request.setRawHeader("Cache-Control", "no-cache");
      
      QNetworkReply *reply = m_networkManager->post(request, bytes);
      sound->setParent(reply);
      
      connect(reply, &QNetworkReply::finished, this, [=]() {
          if (reply->error() != QNetworkReply::NoError) {
              qDebug() << "Error: " + QString(reply->errorString());
          }
      
          QVariant statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute );
          qDebug() << "Status code: " + statusCode.toString();
      });
      

      There is no error and the returned status code is 200. The problem is I can hear only a very quick sound lasting less than a second.

      I think the problem lies in the fact that I am uploading the whole file at once while it is expected to be streamed in real-time (it should be a voice transmission).

      How do I stream the file as if it was live voice recording instead of uploading it all at once?

      aha_1980A Offline
      aha_1980A Offline
      aha_1980
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi @Jansi said in Streaming audio file to a network camera:

      I think the problem lies in the fact that I am uploading the whole file at once while it is expected to be streamed in real-time (it should be a voice transmission).

      Might be, but the API clearly states:

      Codec: When using this API audio MUST be G.711 μ-law (sampling rate 8000Hz)

      So if you have a file with the correct codec and sample rate (and small enough to be transmitted at once), it will be played in real time, as there is no other way as to play 8000 samples per second.

      The document also gave the hint to use Wireshark for debugging, maybe use some official software first and see how data is transmitted?

      Regards

      How do I stream the file as if it was live voice recording instead of uploading it all at once?

      Qt has to stay free or it will die.

      JansiJ 1 Reply Last reply
      2
      • JansiJ Jansi

        Hi, I have a Doorbird doorbell and I am trying to use its API to play a sound. The request should look like this:

        POST /bha-api/audio-transmit.cgi HTTP/1.0\r\n
        Content-Type: audio/basic\r\n
        Content-Length: 9999999\r\n
        Connection: Keep-Alive\r\n
        Cache-Control: no-cache\r\n
        \r\n
        <AUDIO DATA>
        <AUDIO DATA>
        <AUDIO DATA>
        ...
        

        I am sending the sound file using QNetworkAccessManager like this:

        QNetworkRequest request(m_url);
        
        QFile *sound = new QFile(":/resources/test.wav");
        if(!sound->open(QIODevice::ReadOnly)) { }
        
        QByteArray bytes = sound->readAll();
        
        request.setHeader(QNetworkRequest::ContentTypeHeader, "audio/basic");
        request.setHeader(QNetworkRequest::ContentLengthHeader, "9999999");
        request.setRawHeader("Connection", "Keep-Alive");
        request.setRawHeader("Cache-Control", "no-cache");
        
        QNetworkReply *reply = m_networkManager->post(request, bytes);
        sound->setParent(reply);
        
        connect(reply, &QNetworkReply::finished, this, [=]() {
            if (reply->error() != QNetworkReply::NoError) {
                qDebug() << "Error: " + QString(reply->errorString());
            }
        
            QVariant statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute );
            qDebug() << "Status code: " + statusCode.toString();
        });
        

        There is no error and the returned status code is 200. The problem is I can hear only a very quick sound lasting less than a second.

        I think the problem lies in the fact that I am uploading the whole file at once while it is expected to be streamed in real-time (it should be a voice transmission).

        How do I stream the file as if it was live voice recording instead of uploading it all at once?

        Pablo J. RoginaP Offline
        Pablo J. RoginaP Offline
        Pablo J. Rogina
        wrote on last edited by
        #3

        @Jansi said in Streaming audio file to a network camera:

        ...
        QFile *sound = new QFile(":/resources/test.wav");
        if(!sound->open(QIODevice::ReadOnly)) { }
         
        QByteArray bytes = sound->readAll();
        ...
        

        In addition to the good suggestions from @aha_1980 your code is actually going on even if the sound file cannot be opened, your check is flawed since you're doing nothing in case of open error...

        Upvote the answer(s) that helped you solve the issue
        Use "Topic Tools" button to mark your post as Solved
        Add screenshots via postimage.org
        Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

        1 Reply Last reply
        2
        • Christian EhrlicherC Online
          Christian EhrlicherC Online
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @Pablo-J-Rogina said in Streaming audio file to a network camera:

          QFile *sound

          No need to create it on the heap (and then forgot to delete it) :)

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          Pablo J. RoginaP 1 Reply Last reply
          1
          • Christian EhrlicherC Christian Ehrlicher

            @Pablo-J-Rogina said in Streaming audio file to a network camera:

            QFile *sound

            No need to create it on the heap (and then forgot to delete it) :)

            Pablo J. RoginaP Offline
            Pablo J. RoginaP Offline
            Pablo J. Rogina
            wrote on last edited by
            #5

            @Christian-Ehrlicher yeah, I've just copied/pasted OP code snippet just with focus on the open() check but missed that one, good catch.

            Upvote the answer(s) that helped you solve the issue
            Use "Topic Tools" button to mark your post as Solved
            Add screenshots via postimage.org
            Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

            1 Reply Last reply
            0
            • aha_1980A aha_1980

              Hi @Jansi said in Streaming audio file to a network camera:

              I think the problem lies in the fact that I am uploading the whole file at once while it is expected to be streamed in real-time (it should be a voice transmission).

              Might be, but the API clearly states:

              Codec: When using this API audio MUST be G.711 μ-law (sampling rate 8000Hz)

              So if you have a file with the correct codec and sample rate (and small enough to be transmitted at once), it will be played in real time, as there is no other way as to play 8000 samples per second.

              The document also gave the hint to use Wireshark for debugging, maybe use some official software first and see how data is transmitted?

              Regards

              How do I stream the file as if it was live voice recording instead of uploading it all at once?

              JansiJ Offline
              JansiJ Offline
              Jansi
              wrote on last edited by
              #6

              @aha_1980 said in Streaming audio file to a network camera:

              Codec: When using this API audio MUST be G.711 μ-law (sampling rate 8000Hz)

              I recorded a message using Audacity, saved it to a WAV and then recoded the file using ffmpeg like this: ffmpeg -i record.wav -codec:a pcm_mulaw -ac 1 -ar 8000 test.wav, so it should be the correct format and it's only 7,3 kilobytes:

              $ file test.wav
              test.wav: RIFF (little-endian) data, WAVE audio, ITU G.711 mu-law, mono 8000 Hz
              

              One thing I noticed is that Qt overwrites the Content-Lenght to the "correct" size of the file instead of 99999999 that I set manually. It also sets other headers, so maybe that's the issue.

              Wireshark

              @Pablo-J-Rogina said in Streaming audio file to a network camera:

              your check is flawed since you're doing nothing in case of open error...

              I just omitted that part to make the code shorter.

              1 Reply Last reply
              0
              • JansiJ Offline
                JansiJ Offline
                Jansi
                wrote on last edited by
                #7

                OK, so I used QTcpSocket and it sort of works now. After a lot of trial and error, I found that if I write the headers, then flush, then write the sound bytes and then sleep for one second, the sound will be played. If I remove either the flush() or the sleep() call then the sound is not played.

                void DoorbirdClient::doConnect()
                {
                    socket = new QTcpSocket(this);
                
                    connect(socket, SIGNAL(connected()), this, SLOT(connected()));
                    connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
                    connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWritten(qint64)));
                    connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
                
                    socket->connectToHost(m_url.host(), 80);
                
                    if(!socket->waitForConnected(5000))
                    {
                        qDebug() << "Error: " << socket->errorString();
                    }
                }
                
                void DoorbirdClient::connected()
                {
                    const char* postHeader = QString("POST /bha-api/audio-transmit.cgi?sessionid=" + m_securityToken + " HTTP/1.0\r\n").toUtf8().constData();
                    socket->write(postHeader);
                    socket->write("Content-Type: audio/basic\r\n");
                    socket->write("Content-Length: 9999999\r\n");
                    socket->write("Connection: Keep-Alive\r\n");
                    socket->write("Cache-Control: no-cache\r\n");
                    socket->write("\r\n");
                
                    QFile sound(":/resources/test.wav");
                    if(!sound.open(QIODevice::ReadOnly)) {
                        qDebug() << "Sound file could not be opened";
                        socket->disconnectFromHost();
                        return;
                    }
                
                    QByteArray bytes = sound.readAll();
                
                    qDebug() << "Sending sound bytes";
                
                    socket->flush();
                    socket->write(bytes);
                    sleep(1);
                }
                

                I highly doubt that using sleep() while writing to a socket is the proper solution though...

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved