Fixed localstream executable
This commit is contained in:
parent
687e9e32f9
commit
10e45123c4
4 changed files with 101 additions and 71 deletions
|
@ -10,7 +10,7 @@ import urllib.parse
|
|||
from platypush.config import Config
|
||||
from platypush.context import get_plugin
|
||||
from platypush.plugins import Plugin, action
|
||||
from platypush.utils import get_ip_or_hostname
|
||||
from platypush.utils import get_ip_or_hostname, is_process_alive
|
||||
|
||||
class PlayerState(enum.Enum):
|
||||
STOP = 'stop'
|
||||
|
@ -42,8 +42,8 @@ class MediaPlugin(Plugin):
|
|||
# Default port for the local resources HTTP streaming service
|
||||
_default_streaming_port = 8989
|
||||
|
||||
_local_stream_bin = os.path.join(os.path.dirname(__file__), 'bin',
|
||||
'localstream')
|
||||
# setup.py install will place localstream in PATH
|
||||
_local_stream_bin = 'localstream'
|
||||
|
||||
_NOT_IMPLEMENTED_ERR = NotImplementedError(
|
||||
'This method must be implemented in a derived class')
|
||||
|
@ -360,7 +360,7 @@ class MediaPlugin(Plugin):
|
|||
|
||||
self._streaming_proc = subprocess.Popen(
|
||||
[self._local_stream_bin, media, str(self._streaming_port)],
|
||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||
)
|
||||
|
||||
threading.Thread(target=self._streaming_process_monitor(media)).start()
|
||||
|
@ -388,9 +388,24 @@ class MediaPlugin(Plugin):
|
|||
if not self._streaming_proc:
|
||||
return
|
||||
|
||||
while True:
|
||||
if not self._streaming_proc or not \
|
||||
is_process_alive(self._streaming_proc.pid):
|
||||
break
|
||||
|
||||
line = self._streaming_proc.stdout.readline().decode().strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
if line.startswith('Listening on'):
|
||||
break
|
||||
|
||||
self.logger.info('Message from streaming service: {}'.format(line))
|
||||
|
||||
self._streaming_proc.wait()
|
||||
try: self.stop_streaming()
|
||||
except: pass
|
||||
self.logger.info('Streaming service terminated')
|
||||
|
||||
return _thread
|
||||
|
||||
|
|
|
@ -1,71 +1,14 @@
|
|||
#!/usr/bin/env node
|
||||
#!/bin/bash
|
||||
|
||||
// Requires:
|
||||
// - express (`npm install express`)
|
||||
// - mime-types (`npm install mime-types`)
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
const express = require('express')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const process = require('process')
|
||||
const mime = require('mime-types')
|
||||
const app = express()
|
||||
if [ -d "$HOME/node_modules" ]; then
|
||||
export NODE_PATH=$HOME/node_modules:$NODE_PATH
|
||||
fi
|
||||
|
||||
function parseArgv() {
|
||||
let file = undefined
|
||||
let port = 8989
|
||||
file=$1
|
||||
port=
|
||||
[ ! -z "$2" ] && port=$2
|
||||
|
||||
if (process.argv.length < 3) {
|
||||
throw Error(`Usage: ${process.argv[0]} ${process.argv[1]} <media_file> [port=${port}]`)
|
||||
}
|
||||
node $DIR/localstream.js "$file" $port
|
||||
|
||||
file = process.argv[2]
|
||||
|
||||
if (process.argv.length > 3) {
|
||||
port = parseInt(process.argv[3])
|
||||
}
|
||||
|
||||
return { file: file, port: port }
|
||||
}
|
||||
|
||||
let args = parseArgv()
|
||||
|
||||
app.get('/video', function(req, res) {
|
||||
const path = args.file
|
||||
const ext = args.file.split('.').pop()
|
||||
const stat = fs.statSync(path)
|
||||
const fileSize = stat.size
|
||||
const range = req.headers.range
|
||||
const mimeType = mime.lookup(ext)
|
||||
|
||||
if (range) {
|
||||
const parts = range.replace(/bytes=/, "").split("-")
|
||||
const start = parseInt(parts[0], 10)
|
||||
const end = parts[1]
|
||||
? parseInt(parts[1], 10)
|
||||
: fileSize-1
|
||||
|
||||
const chunksize = (end-start)+1
|
||||
const file = fs.createReadStream(path, {start, end})
|
||||
const head = {
|
||||
'Content-Range': `bytes ${start}-${end}/${fileSize}`,
|
||||
'Accept-Ranges': 'bytes',
|
||||
'Content-Length': chunksize,
|
||||
'Content-Type': mimeType,
|
||||
}
|
||||
|
||||
res.writeHead(206, head)
|
||||
file.pipe(res)
|
||||
} else {
|
||||
const head = {
|
||||
'Content-Length': fileSize,
|
||||
'Content-Type': mimeType,
|
||||
}
|
||||
res.writeHead(200, head)
|
||||
fs.createReadStream(path).pipe(res)
|
||||
}
|
||||
})
|
||||
|
||||
app.listen(args.port, function () {
|
||||
console.log(`Listening on port ${args.port}`)
|
||||
})
|
||||
|
|
71
platypush/plugins/media/bin/localstream.js
Executable file
71
platypush/plugins/media/bin/localstream.js
Executable file
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
// Requires:
|
||||
// - express (`npm install express`)
|
||||
// - mime-types (`npm install mime-types`)
|
||||
|
||||
const express = require('express')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const process = require('process')
|
||||
const mime = require('mime-types')
|
||||
const app = express()
|
||||
|
||||
function parseArgv() {
|
||||
let file = undefined
|
||||
let port = 8989
|
||||
|
||||
if (process.argv.length < 3) {
|
||||
throw Error(`Usage: ${process.argv[0]} ${process.argv[1]} <media_file> [port=${port}]`)
|
||||
}
|
||||
|
||||
file = process.argv[2]
|
||||
|
||||
if (process.argv.length > 3) {
|
||||
port = parseInt(process.argv[3])
|
||||
}
|
||||
|
||||
return { file: file, port: port }
|
||||
}
|
||||
|
||||
let args = parseArgv()
|
||||
|
||||
app.get('/video', function(req, res) {
|
||||
const path = args.file
|
||||
const ext = args.file.split('.').pop()
|
||||
const stat = fs.statSync(path)
|
||||
const fileSize = stat.size
|
||||
const range = req.headers.range
|
||||
const mimeType = mime.lookup(ext)
|
||||
|
||||
if (range) {
|
||||
const parts = range.replace(/bytes=/, "").split("-")
|
||||
const start = parseInt(parts[0], 10)
|
||||
const end = parts[1]
|
||||
? parseInt(parts[1], 10)
|
||||
: fileSize-1
|
||||
|
||||
const chunksize = (end-start)+1
|
||||
const file = fs.createReadStream(path, {start, end})
|
||||
const head = {
|
||||
'Content-Range': `bytes ${start}-${end}/${fileSize}`,
|
||||
'Accept-Ranges': 'bytes',
|
||||
'Content-Length': chunksize,
|
||||
'Content-Type': mimeType,
|
||||
}
|
||||
|
||||
res.writeHead(206, head)
|
||||
file.pipe(res)
|
||||
} else {
|
||||
const head = {
|
||||
'Content-Length': fileSize,
|
||||
'Content-Type': mimeType,
|
||||
}
|
||||
res.writeHead(200, head)
|
||||
fs.createReadStream(path).pipe(res)
|
||||
}
|
||||
})
|
||||
|
||||
app.listen(args.port, function () {
|
||||
console.log(`Listening on port ${args.port}`)
|
||||
})
|
3
setup.py
3
setup.py
|
@ -49,7 +49,8 @@ setup(
|
|||
'platydock=platypush.platydock:main',
|
||||
],
|
||||
},
|
||||
scripts = ['bin/platyvenv'],
|
||||
scripts = ['bin/platyvenv', 'platypush/plugins/media/bin/localstream.js',
|
||||
'platypush/plugins/media/bin/localstream'],
|
||||
# data_files = [
|
||||
# ('/etc/platypush', ['platypush/config.example.yaml'])
|
||||
# ],
|
||||
|
|
Loading…
Reference in a new issue