Compare commits
5 Commits
8731b7c4ec
...
5a9d6e265c
Author | SHA1 | Date |
---|---|---|
Fierelier | 5a9d6e265c | |
Fierelier | 2ef0d0654a | |
Fierelier | 220c0005ba | |
Fierelier | a69d881f95 | |
Fierelier | 77e862f280 |
|
@ -12,14 +12,13 @@ Accepts data from stdin, and sends it to the specified server.
|
|||
- **`user-password`**: Your user's password.
|
||||
- **`channel`**: The channel you wanna stream to. Can be any name.
|
||||
- **`channel-password`**: The channel's password.
|
||||
- **`loop-delay`**: How long should the server wait between each acquisition of data, in seconds? Higher values will cause more delay, but will also store more data in the backlog (good for laggy watchers). Lower values for lower delay.
|
||||
|
||||
All arguments are optional but for `user`.
|
||||
|
||||
### Example
|
||||
`ffmpeg -f gdigrab -framerate 30 -i desktop -vf scale=-2:480 -c:v libx264 -pix_fmt yuv420p -maxrate 1M -f h264 - | fstream.py 127.0.0.1:61920 broadcast,user=fier,user-password=123,delay=0.1,channel=exampleChannel,channel-password=456`
|
||||
`ffmpeg -f gdigrab -framerate 30 -i desktop -vf scale=-2:480 -c:v libx264 -pix_fmt yuv420p -maxrate 1M -f h264 - | fstream.py 127.0.0.1:61920 broadcast,user=fier,user-password=123,channel=exampleChannel,channel-password=456`
|
||||
|
||||
Broadcast Windows desktop as `fier` to `127.0.0.1:61920`, supplying `123` as the user password with a server loop-delay of `0.1` seconds. `exampleChannel` is the channel, `456` is the channel's password. Pipe the output from ffmpeg.
|
||||
Broadcast Windows desktop as `fier` to `127.0.0.1:61920`, supplying `123` as the user password. `exampleChannel` is the channel, `456` is the channel's password. Pipe the output from ffmpeg.
|
||||
|
||||
## Watch
|
||||
`fstream.py <ip:port> broadcast,[key=value],[key=value],...`
|
||||
|
@ -54,6 +53,6 @@ If you would like to implement your own authentication, make your own module to
|
|||
Establish a TCP connection with the server, and send the payload. If the server likes your payload, it will stream data to you, or accept more of your data.
|
||||
|
||||
## The payload
|
||||
Send the length of the payload as a 4-byte (32-bit) big endian unsigned integer, a null byte (hex:`00`) and a UTF-8 encoded string identifying the client's intentions follows, for example: `watch,user=fier,channel=exampleChannel,channel-password=123` or `broadcast,user=fier,user-password=123,delay=0.1,channel=exampleChannel,channel-password=456`. The length includes only the string message, in bytes, it does not include the length itself, nor the null byte.
|
||||
Send the length of the payload as a 4-byte (32-bit) big endian unsigned integer, a null byte (hex:`00`) and a UTF-8 encoded string identifying the client's intentions follows, for example: `watch,user=fier,channel=exampleChannel,channel-password=123` or `broadcast,user=fier,user-password=123,channel=exampleChannel,channel-password=456`. The length includes only the string message, in bytes, it does not include the length itself, nor the null byte.
|
||||
|
||||
If you are a watcher, you will now be blasted with data. If you are a broadcaster, you can now blast data.
|
|
@ -121,7 +121,9 @@ def main():
|
|||
eprint("Receiving data...")
|
||||
while True:
|
||||
data = connection.recv(bufferSize)
|
||||
if data == b"": return
|
||||
if data == b"":
|
||||
eprint("Connection closed.")
|
||||
return
|
||||
unbufferedStdout.write(data)
|
||||
except:
|
||||
connection.close()
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
global select
|
||||
import select
|
||||
global time
|
||||
import time
|
||||
|
||||
global clientLoopIn
|
||||
def clientLoopIn(self):
|
||||
|
@ -16,13 +14,6 @@ def clientLoopIn(self):
|
|||
|
||||
if not "channel" in args: args["channel"] = "default"
|
||||
if not "channel-password" in args: args["channel-password"] = ""
|
||||
if not "delay" in args: args["delay"] = 0.1
|
||||
if not "user-password" in args: args["user-password"] = ""
|
||||
args["delay"] = float(args["delay"])
|
||||
if args["delay"] < minDelay: args["delay"] = minDelay
|
||||
if args["delay"] > maxDelay: args["delay"] = maxDelay
|
||||
|
||||
if not authenticate(args["user"],args["user-password"]): return
|
||||
|
||||
with clientDataLock:
|
||||
setClientData(self.cID,"type",cmd[0])
|
||||
|
@ -37,13 +28,12 @@ def clientLoopIn(self):
|
|||
setClientData(self.cID,"queue",q)
|
||||
|
||||
if cmd[0] == "broadcast":
|
||||
if not authenticate(args["user"],args["user-password"]): return
|
||||
buffer = getClientData(self.cID,"buffer")
|
||||
packet = -1
|
||||
packetMin = 0
|
||||
bufferSize = 0
|
||||
lastReceived = time.process_time()
|
||||
while True:
|
||||
args["delay"] = 0
|
||||
data = self.connection.recv(connBuffer)
|
||||
if data == b"": return
|
||||
with clientDataLock:
|
||||
|
@ -51,7 +41,7 @@ def clientLoopIn(self):
|
|||
if dataSize > maxBuffer: return
|
||||
bufferSize += dataSize + bufferCost
|
||||
while bufferSize > maxBuffer:
|
||||
bufferSize -= len(buffer[str(packetMin)]) - bufferCost
|
||||
bufferSize -= len(buffer[str(packetMin)]) + bufferCost
|
||||
del buffer[str(packetMin)]
|
||||
packetMin += 1
|
||||
packet += 1
|
||||
|
@ -61,12 +51,6 @@ def clientLoopIn(self):
|
|||
for cID in clients:
|
||||
if getClientData(cID,"type") == "watch" and getClientData(cID,"args")["user"] == args["user"] and getClientData(cID,"args")["channel"] == args["channel"] and getClientData(cID,"args")["channel-password"] == args["channel-password"]:
|
||||
getClientData(cID,"queue").put("")
|
||||
|
||||
now = time.process_time()
|
||||
timeSpent = now - lastReceived
|
||||
wait = args["delay"] - timeSpent
|
||||
if wait > 0: time.sleep(wait)
|
||||
lastReceived = now
|
||||
|
||||
if cmd[0] == "watch":
|
||||
packet = -1
|
||||
|
|
|
@ -3,8 +3,4 @@ connBuffer = 1024 # How large can a buffer piece be in bytes?
|
|||
global bufferCost
|
||||
bufferCost = 1024 # Virtually add extra cost to each buffer piece to prevent clients from overloading the server by sending super small pieces.
|
||||
global maxBuffer
|
||||
maxBuffer = 20*1024*1024 # The maximum buffer size of a stream in bytes. Old buffers are discarded, clients that depend on them get disconnected.
|
||||
global minDelay
|
||||
minDelay = 0.05 # The minimum delay (pause between each buffer iteration) the user can set in seconds. Lower values cause higher CPU usage.
|
||||
global maxDelay
|
||||
maxDelay = 1 # The maximum delay the user can set.
|
||||
maxBuffer = 20*1024*1024 # The maximum buffer size of a stream in bytes. Old buffers are discarded, clients that depend on them get disconnected.
|
Loading…
Reference in New Issue