| #!/usr/bin/env bash |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| set -euo pipefail |
|
|
| |
| if [ "${1:-}" = "--from-file" ] && [ -f "${2:-}" ]; then |
| JSON=$(cat "$2") |
| elif [ -n "${1:-}" ] && [ "${1:-}" != "-" ]; then |
| JSON="$1" |
| else |
| JSON=$(cat) |
| fi |
|
|
| if [ -z "$JSON" ]; then |
| echo "Error: No stream JSON provided" |
| echo "Usage: ./play-stream.sh '<json>' or pipe JSON to stdin" |
| exit 1 |
| fi |
|
|
| |
| if command -v jq &>/dev/null; then |
| STREAM_URL=$(echo "$JSON" | jq -r '.manifest_url // .videos[0].url // empty') |
| |
| HEADERS=$(echo "$JSON" | jq -r '.headers[]? | "\(.key): \(.value)"') |
| FORMAT=$(echo "$JSON" | jq -r '.format // "hls"') |
| LABEL=$(echo "$JSON" | jq -r '.label // "Stream"') |
| elif command -v python3 &>/dev/null; then |
| STREAM_URL=$(echo "$JSON" | python3 -c " |
| import json, sys |
| d = json.load(sys.stdin) |
| url = d.get('manifest_url') or (d.get('videos', [{}])[0].get('url', '')) |
| print(url) |
| ") |
| HEADERS=$(echo "$JSON" | python3 -c " |
| import json, sys |
| d = json.load(sys.stdin) |
| for h in d.get('headers', []): |
| print(f\"{h['key']}: {h['value']}\") |
| ") |
| FORMAT=$(echo "$JSON" | python3 -c " |
| import json, sys |
| d = json.load(sys.stdin) |
| print(d.get('format', 'hls')) |
| ") |
| LABEL="Stream" |
| else |
| echo "Error: requires 'jq' or 'python3' to parse JSON" |
| exit 1 |
| fi |
|
|
| if [ -z "$STREAM_URL" ]; then |
| echo "Error: Could not extract stream URL from JSON" |
| echo "JSON received:" |
| echo "$JSON" | head -20 |
| exit 1 |
| fi |
|
|
| echo "=== BEX Stream Player ===" |
| echo "URL: $STREAM_URL" |
| echo "Format: $FORMAT" |
| echo "Label: $LABEL" |
| echo "" |
|
|
| |
| MPV_HEADERS="" |
| FFPLAY_HEADERS="" |
|
|
| while IFS= read -r header; do |
| if [ -n "$header" ]; then |
| KEY=$(echo "$header" | cut -d: -f1 | xargs) |
| VALUE=$(echo "$header" | cut -d: -f2- | xargs) |
| MPV_HEADERS="${MPV_HEADERS}${KEY}: ${VALUE}\r\n" |
| FFPLAY_HEADERS="${FFPLAY_HEADERS}-headers \"${KEY}: ${VALUE}\r\n\" " |
| echo "Header: $KEY: $VALUE" |
| fi |
| done <<< "$HEADERS" |
|
|
| echo "" |
|
|
| |
| if command -v mpv &>/dev/null; then |
| echo "Playing with mpv..." |
| MPV_ARGS=( |
| "$STREAM_URL" |
| "--title=BEX: $LABEL" |
| "--force-media-title=$LABEL" |
| ) |
|
|
| if [ -n "$MPV_HEADERS" ]; then |
| MPV_ARGS+=("--http-header-fields=${MPV_HEADERS}") |
| fi |
|
|
| |
| if [ "$FORMAT" = "hls" ] || echo "$STREAM_URL" | grep -q "m3u8"; then |
| MPV_ARGS+=( |
| "--demuxer-max-bytes=100MiB" |
| "--demuxer-max-back-bytes=50MiB" |
| "--cache=yes" |
| "--cache-secs=30" |
| ) |
| fi |
|
|
| exec mpv "${MPV_ARGS[@]}" |
|
|
| |
| elif command -v ffplay &>/dev/null; then |
| echo "Playing with ffplay..." |
| FFPLAY_ARGS=( |
| -i "$STREAM_URL" |
| -window_title "BEX: $LABEL" |
| -loglevel warning |
| -autoexit |
| ) |
|
|
| if [ -n "$MPV_HEADERS" ]; then |
| FFPLAY_ARGS+=(-headers "$MPV_HEADERS") |
| fi |
|
|
| exec ffplay "${FFPLAY_ARGS[@]}" |
|
|
| |
| else |
| echo "No player found (mpv or ffplay required)" |
| echo "" |
| echo "Manual playback commands:" |
| echo "" |
| echo " mpv \"$STREAM_URL\" \\" |
| if [ -n "$MPV_HEADERS" ]; then |
| echo " --http-header-fields=\"${MPV_HEADERS}\" \\" |
| fi |
| echo " --cache=yes" |
| echo "" |
| echo " ffplay -i \"$STREAM_URL\" \\" |
| if [ -n "$MPV_HEADERS" ]; then |
| echo " -headers \"${MPV_HEADERS}\"" |
| fi |
| echo "" |
| echo " curl -L -H 'User-Agent: Mozilla/5.0' \"$STREAM_URL\" | ffplay -" |
| exit 1 |
| fi |
|
|