0

I want to get audio streaming data from server using Python.

I try simple request to audio stream url using urllib:

req = urllib.request.Request(<url>)

but i get exception:

http.client.BadStatusLine: Uª¨Ì5¦`

It looks like server responses and send data without http header including Status code.

Is there any way to get and process response in this case?

Also it is worth to mention results i got to request this URL with clients:

  1. Curl:

curl "http://<server>:81/audiostream.cgi?user=<user>&pwd=<password>&streamid=0&filename=" curl: (1) Received HTTP/0.9 when not allowed

The workaround is use --http0.9 switch.

  1. Chrome/Chromium based browsers shows:

ERR_INVALID_HTTP_RESPONSE

  1. Mozilla Firefox can correctly fetch this data as binary

Screenshot

alexeynl
  • 11
  • 5
  • Technically speaking http 0.9 can only return *hypertext*, so this isn't a valid http 0.9 response. It's probably simplest to handle this manually with a socket, if it is in fact sending the binary in response to a get request. (send the GET and then to socket.recv()). – 2e0byo Feb 16 '23 at 15:21
  • FWIW it looks like cpython lost http 0.9 [quite a while ago](https://github.com/python/cpython/issues/54920). It's about the simplest imaginable protocol, however, and perfectly implementable in pure python. – 2e0byo Feb 16 '23 at 15:22

2 Answers2

0

Have you tried including User-Agent header when doing this request? Sometimes this can be caused by a web-scraping detection.

import urllib2

opener = urllib2.build_opener()

headers = {
  'User-Agent': 'Mozilla/5.0 (Windows NT 5.1; rv:10.0.1) Gecko/20100101 Firefox/10.0.1',
}

opener.addheaders = headers.items()
response = opener.open(<url>)
0

HTTP 0.9 is about the simplest possible http protocol:

The client sends a document request consisting of a line of ASCII characters terminated by a CR LF (carriage return, line feed) pair [...] This request consists of the word "GET", a space, the document address , omitting the "http:, host and port parts when they are the coordinates just used to make the connection.

The response to a simple GET request is a message in hypertext mark-up language ( HTML ). This is a byte stream of ASCII characters.

source

Thus your server is not sending a valid HTTP 0.9 response, as it's not html. Chrome (etc) is quite within its rights to reject it, although in practice it may not even support http 0.9.

In this case the camera is apparently (ab)using http to start a stream (since presumably it will carry on sending data over the connection, which is also not http 0.9, although not explicitly forbidden). The simplest way to get the data you want is to do it manually:

  • Create and open a socket with the server's base address
  • send a GET request for audiostream.cgi?user=<user>&pwd=<password>&streamid=0&filename= (do you really need that last param?)
  • run socket.recv(max_bytes) in a loop in a thread and transfer to a (thread-safe) buffer, do whatever you want to do with that buffer in another thread.

Alternatively if you're familiar with async programming, use asyncio rather than threads.

You will obviously need to handle decoding the file stream yourself. Hopefully you can identify the format and pass it to a decoder; alternatively something like ffmpeg might be able to guess it.

2e0byo
  • 5,305
  • 1
  • 6
  • 26
  • Thank you very much for your support. You have explained everything and gave me a right direction. The work around code is: `import socket s=socket.connect(("", )) s.socket.send(b"GET /audiostream.cgi?user=&pwd=&streamid=0&filename= HTTP/1.1\r\nHost:\r\n\r\n") s.stream = self.socket.recv()` – alexeynl Feb 17 '23 at 11:38