How do I pass an image to an RTMP address in Python? - sockets

My goal is to stream a video to an RTMP link. I have gotten this to work by saving the video (.mp4) to a file and then using FFmpeg to stream the file to the link. However, I want to make this process faster, so I want to stream without going through the file system. My idea was to set up a client using the socket library and send the data to the RTMP server I have running via NGINX:
images = [img_as_ubyte(frame) for frame in predictions] # Contains the images that make up the video
PORT = 1935
SERVER = "localhost/live/face" # Desired RTMP Address: rtmp://localhost/live/face or rtmp://localhost:1935/live/face
ADDR = (SERVER, PORT)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)
for img in images:
send = client.send(img)
I've tried putting many different things in the SERVER variable (e.g. rtmp://localhost/live/face, localhost, etc.) and I can't seem to fix the errors I've been getting (socket.gaierror: [Errno -2] Name or service not known or ConnectionRefusedError: [Errno 111] Connection refused). Does someone have any advice as to how I should pass the data to the RTMP link?
Additionally, here is my nginx.conf file:
worker_processes auto;
events {
worker_connections 768;
# multi-accept on;
}
rtmp {
server {
listen 1935;
application live {
live on;
interleave on;
hls on;
hls_path /tmp/hls;
hls_fragment 3s;
}
}
}
http {
default_type application/octet-stream;
server {
listen 4040;
#location /tv {
#root /tmp/hls/;
#}
location / {
root /tmp;
}
}
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
text/html html;
}
}

Related

Prevent nginx from killing idle tcp sockets

I'm trying to use nginx as a reverse proxy for ssl/tcp sockets (so that I can write my server custom as raw tcp, but have nginx handle the ssl certificates). My use case requires the tcp connections remain alive, but to go idle (no packets back and forth) for extended periods of time (determined by the client, but as long as an hour). Unfortunately, nginx kills my socket connections after the first 10 minutes (timed to within a second) of inactivity, and I haven't been able to find either online or in the docs what actually controls this timeout.
I know that it has to be nginx doing it (not my raw server timing out, or my client's ssl socket), since I can directly connect to the server's raw tcp server without timeout issues, but if I run nginx as a raw tcp reverse proxy (no ssl) it does timeout.
Here's some code to reproduce the issue, note that I've commented out the ssl relevent pieces in nginx because the timeout occurs either way.
/etc/nginx/modules-enabled/test.conf:
stream {
upstream tcp-server {
server localhost:33445;
}
server {
listen 33446;
# listen 33446 ssl;
proxy_pass tcp-server;
# Certs
# ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
}
}
server.js;
const net = require("net");
const s = net.createServer();
s.on("connection", (sock) => {
console.log('Got connection from', sock.remoteAddress, sock.remotePort );
sock.on("error", (err) => {
console.error(err)
clearInterval(i);
});
sock.on("close", () => {
console.log('lost connection from', sock.remoteAddress, sock.remotePort );
clearInterval(i);
});
});
s.listen(33445);
client.js
const net = require('net');
const host = 'example.com';
let use_tls = false;
let client;
let start = Date.now()
// Use me to circumvent nginx, and no timeout occurs
// let port = 33445;
// Use me to use nginx, and no timeouts occur after 10 mins of no RX/TX
let port = 33446;
client = new net.Socket();
client.connect({ port, host }, function() {
console.log('Connected via TCP');
// Include me, and nginx doesn't kill the socket
// setInterval(() => { client.write("ping") }, 5000);
});
client.on('end', function() {
console.log('Disconnected: ' + ((Date.now() - start)/1000/60) + " mins");
});
I've tried various directives in the nginx stream block, but nothing seems to help. Thanks in advance!

MqttBrowserClient fails to connect due to missing conack package

I am trying to make webapp over flutter which will connect to HIVE broker. I took the broker name from the official website, set the port number to 8000 just like mentioned there and still get the error message as below:
error is mqtt-client::NoConnectionException: The maximum allowed connection attempts ({1}) were exceeded. The broker is not responding to the connection request message (Missing Connection Acknowledgement?
I really have no clue how to proceed. Can someone please help?
Below is my code:
MqttBrowserClient mq = MqttBrowserClient(
'wss://broker.mqttdashboard.com:8000', '',
maxConnectionAttempts: 1);
/*
MqttBrowserClient mq = MqttBrowserClient('ws://test.mosquitto.org', 'client-1',
maxConnectionAttempts: 1);
*/
class mqttService {
Future<MqttBrowserClient?> connectToServer() async {
try {
final connMess = MqttConnectMessage()
.withClientIdentifier('clientz5tWzoydVL')
.authenticateAs('a14guguliye', 'z5tWzoydVL')
.withWillTopic('willtopic')
.withWillMessage('My Will message')
.startClean() // Non persistent session for testing
.withWillQos(MqttQos.atLeastOnce);
mq.port = 1883;
mq.keepAlivePeriod = 50;
mq.connectionMessage = connMess;
mq.websocketProtocols = MqttClientConstants.protocolsSingleDefault;
mq.onConnected = onConnected;
var status = await mq.connect();
return mq;
} catch (e) {
print("error is " + e.toString());
mq.disconnect();
return null;
}
}
}
That port 8000 may be open but the HiveMQ broker may not be listening.
Make sure that the broker is fully booted and binds to that IP:Port combo.
In the HiveMQ broker startup output, you should see something similar to:
Started Websocket Listener on address 0.0.0.0 and on port 8000
If needed, the HiveMQ Broker configuration documentation is here.
You can use the public HiveMQ MQTT Websocket demo client to test your connection to make sure it's not a local code issue.
As a last option, use Wireshark to monitor MQTT traffic with a filter of tcp.port == 8000 and mqtt

WLAN issue: wlan auto-connects upon entering function body

I have a Pycom Lopy 4 that will recieve sensor readings from another MCU and structure the received data before sending it on to an MQTT server. To achieved that, I initialised the WLAN mode of my LoPy4 to 'STA_AP'.
However, I realised that when i attempted a wlan.disconnect(), and my code enters a function block to deal with the data, wlan.isconnected() returns True again! I know this because I placed a few print statements within the function body to check for connectivity. Below is my code:
import usocket
from network import WLAN
import ustruct
from mqtt import MQTTClient
import machine
sensor_dict = {
0x77 : "bme280"
# Add more sensors here #
}
wlan = WLAN()
## Set static IP address for server
wlan.ifconfig(id = 1, config=('192.168.0.104', '255.255.255.0', '192.168.0.1', '192.168.0.1'))
## Set WLAN mode to STA_AP (station & access point)
print("Setting up wlan access point...")
wlan.init(mode = WLAN.STA_AP, ssid = 'server_layer1', auth = (WLAN.WPA2, 'Password123'), channel=7, antenna=WLAN.INT_ANT)
print("wlan mode set up: with WPA2 auth\n")
## -----------------------------This is the function block---------------------------------- ##
def send_data(data_raw):
print("Unpacking raw data...")
data = ustruct.unpack('lifff', data_raw)
loc, sensor_type, temp, press, hum = data
if wlan.isconnected():
print("connected1")
## Connect to internet
wlan.connect("Name", auth=(WLAN.WPA2, "hahahahaha"), timeout=5000)
if wlan.isconnected():
print("connected3")
while not wlan.isconnected():
machine.idle()
print("Connected to WiFi\n")
print("Sending data up to MQTT server...")
client = MQTTClient("xxx123", "io.adafruit.com",user="yoplo", password="xxx123", port=1883)
client.connect()
client.publish(topic="yoplo/feeds/{}/{}/temp".format(loc, sensor_dict[sensor_type]), msg=temp, retain = True)
## ---------------------------------End of function block------------------------------------- ##
UDP_IP = "0.0.0.0"
UDP_PORT = 6006
## Set up UDP socket and bind
sock = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM) ## UDP
sock.bind((UDP_IP, UDP_PORT))
print('Socket binded.')
data_raw, addr = sock.recvfrom(24) ## buffer size is 24 bytes
## -----------------------------------ran wlan.disconnect() here--------------------------------##
wlan.disconnect()
if wlan.isconnected():
print("connected2")
send_data(data_raw)
machine.deepsleep(10)
My output was:
Setting up wlan access point...
wlan mode set up: with WPA2 auth
Socket binded.
raw data payload: b'q\x01\x00\x00w\x00\x00\x00\xe1z\xd0Aq\xedzD\x14\xae^B'
source: ('192.168.0.105', 49258)
connected2
Unpacking raw data...
connected1
connected3
Connected to WiFi
Sending data up to MQTT server...
Traceback (most recent call last):
File "main.py", line 65, in <module>
File "main.py", line 43, in send_data
File "/flash/lib/mqtt.py", line 66, in connect
OSError: [Errno 113] EHOSTUNREACH
Pycom MicroPython 1.18.2.r6 [v1.8.6-849-a210e85] on 2019-05-13; LoPy4 with ESP32
Type "help()" for more information.
'connected1' and 'connected3' were printed, although 'connected2' was not printed. Not sure why, appreciate any assistance!

How to HTTP POST in Lua without using Lua Socket

I am trying to send a HTTP POST command to an external server from a Lua scripted piece of hardware. In order to do so I have to create a tcpConnection and then do a tcpSend() command. I have confirmed the TCP Connection using wireshark and I have seen it send the HTTP GET command but I do not know how to send a post. I have tried to just change the GET to POST in the code but no avail.
debugConsole = -20
while true do
--Opening connection to remote host
debugConsole = tcpConnect("192.168.1.1", 80, 100)
print("TCP connect " .. debugConsole)
debugConsole = tcpSend("GET /api/v1/profiles/active_profiles.json?profile=5&expiry=1&duration=0&auth_token=2e608b72390a866f4bc7bbb6db63a1aa HTTP/1.1 \r\n\r\n")
print("TCP Send = " .. debugConsole)
--Printing response from remote host
print(responseSubstr(0, 500))
debugConsole = tcpClose()
print("TCP Close = " .. debugConsole)
debugConsole = httpRequest("http://192.168.1.1/api/v1/profiles/active_profiles.json?profile=5&expiry=1&duration=0&auth_token=2e608b72390a866f4bc7bbb6db63a1aa", 10)
print("HTTP Request = " .. debugConsole)
print(" ")
sleep (10000)
end

Sending e-mail via lua nginx timeout error

I'm trying to send e-mail via lua+nginx.
Lapis (Lua) code
local smtp = require("socket.smtp")
app:get("/ee", function(self)
local from = "<mail0#mydns.name>"
local rcpt = {
"<mail1#gmail.com>"
}
local mesgt = {
headers = {
to = "PP <mail1#gmail.com>",
cc = '"V.V." <mail2#gmail.com>',
subject = "My first message"
},
body = "I hope this works. If it does, I can send you another 1000 copies."
}
local r, e = smtp.send{
from = from,
rcpt = rcpt,
source = smtp.message(mesgt),
server = "127.0.0.1",
port = 25
}
return "R:" .. tostring(r) .. " E: " .. tostring(e)
end)
gives timeout error (after several seconds passed): "R: nil E: timeout"
Nginx config is:
http{
server{
listen 9000;
location = /cgi-bin/nginxauth.cgi {
add_header Auth-Status OK;
add_header Auth-Server 127.0.0.1; # backend ip
add_header Auth-Port 25; # backend port
return 200;
}
}
}
mail {
auth_http localhost:9000/cgi-bin/nginxauth.cgi;
server {
server_name mydns.name;
listen 25;
protocol smtp;
proxy on;
timeout 5s;
proxy_pass_error_message on;
#smtp_auth login plain;
xclient on;
smtp_auth none;
}
}
I do not understand the core of mail server. How to configure? How to use nginx server? I think timeout error appears due to mail-server just redirect but doesnt process email data, am I right? Or what have I do to fix with error?