krystv commited on
Commit
2753d8f
·
verified ·
1 Parent(s): ceb9df4

Upload play-stream.sh

Browse files
Files changed (1) hide show
  1. play-stream.sh +155 -0
play-stream.sh ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # Stream playback helper — takes BEX stream JSON output and plays with mpv/ffplay
3
+ #
4
+ # Usage:
5
+ # ./play-stream.sh <stream_json>
6
+ # echo '{"manifest_url":"...", "headers":[...]}' | ./play-stream.sh
7
+ # ./play-stream.sh --from-file stream_output.json
8
+ #
9
+ # Supports:
10
+ # - HLS (.m3u8) streams
11
+ # - Direct MP4/MKV URLs
12
+ # - Custom headers (Referer, User-Agent, etc.)
13
+ # - mpv (preferred) or ffplay (fallback)
14
+ #
15
+ # The script extracts the stream URL and headers from the BEX engine's
16
+ # resolve-stream JSON output and constructs the correct player command.
17
+
18
+ set -euo pipefail
19
+
20
+ # Read JSON from stdin, argument, or file
21
+ if [ "${1:-}" = "--from-file" ] && [ -f "${2:-}" ]; then
22
+ JSON=$(cat "$2")
23
+ elif [ -n "${1:-}" ] && [ "${1:-}" != "-" ]; then
24
+ JSON="$1"
25
+ else
26
+ JSON=$(cat)
27
+ fi
28
+
29
+ if [ -z "$JSON" ]; then
30
+ echo "Error: No stream JSON provided"
31
+ echo "Usage: ./play-stream.sh '<json>' or pipe JSON to stdin"
32
+ exit 1
33
+ fi
34
+
35
+ # Parse JSON with jq (or python fallback)
36
+ if command -v jq &>/dev/null; then
37
+ STREAM_URL=$(echo "$JSON" | jq -r '.manifest_url // .videos[0].url // empty')
38
+ # Extract headers as key: value pairs
39
+ HEADERS=$(echo "$JSON" | jq -r '.headers[]? | "\(.key): \(.value)"')
40
+ FORMAT=$(echo "$JSON" | jq -r '.format // "hls"')
41
+ LABEL=$(echo "$JSON" | jq -r '.label // "Stream"')
42
+ elif command -v python3 &>/dev/null; then
43
+ STREAM_URL=$(echo "$JSON" | python3 -c "
44
+ import json, sys
45
+ d = json.load(sys.stdin)
46
+ url = d.get('manifest_url') or (d.get('videos', [{}])[0].get('url', ''))
47
+ print(url)
48
+ ")
49
+ HEADERS=$(echo "$JSON" | python3 -c "
50
+ import json, sys
51
+ d = json.load(sys.stdin)
52
+ for h in d.get('headers', []):
53
+ print(f\"{h['key']}: {h['value']}\")
54
+ ")
55
+ FORMAT=$(echo "$JSON" | python3 -c "
56
+ import json, sys
57
+ d = json.load(sys.stdin)
58
+ print(d.get('format', 'hls'))
59
+ ")
60
+ LABEL="Stream"
61
+ else
62
+ echo "Error: requires 'jq' or 'python3' to parse JSON"
63
+ exit 1
64
+ fi
65
+
66
+ if [ -z "$STREAM_URL" ]; then
67
+ echo "Error: Could not extract stream URL from JSON"
68
+ echo "JSON received:"
69
+ echo "$JSON" | head -20
70
+ exit 1
71
+ fi
72
+
73
+ echo "=== BEX Stream Player ==="
74
+ echo "URL: $STREAM_URL"
75
+ echo "Format: $FORMAT"
76
+ echo "Label: $LABEL"
77
+ echo ""
78
+
79
+ # Build header arguments
80
+ MPV_HEADERS=""
81
+ FFPLAY_HEADERS=""
82
+
83
+ while IFS= read -r header; do
84
+ if [ -n "$header" ]; then
85
+ KEY=$(echo "$header" | cut -d: -f1 | xargs)
86
+ VALUE=$(echo "$header" | cut -d: -f2- | xargs)
87
+ MPV_HEADERS="${MPV_HEADERS}${KEY}: ${VALUE}\r\n"
88
+ FFPLAY_HEADERS="${FFPLAY_HEADERS}-headers \"${KEY}: ${VALUE}\r\n\" "
89
+ echo "Header: $KEY: $VALUE"
90
+ fi
91
+ done <<< "$HEADERS"
92
+
93
+ echo ""
94
+
95
+ # Try mpv first (best experience)
96
+ if command -v mpv &>/dev/null; then
97
+ echo "Playing with mpv..."
98
+ MPV_ARGS=(
99
+ "$STREAM_URL"
100
+ "--title=BEX: $LABEL"
101
+ "--force-media-title=$LABEL"
102
+ )
103
+
104
+ if [ -n "$MPV_HEADERS" ]; then
105
+ MPV_ARGS+=("--http-header-fields=${MPV_HEADERS}")
106
+ fi
107
+
108
+ # HLS-specific options
109
+ if [ "$FORMAT" = "hls" ] || echo "$STREAM_URL" | grep -q "m3u8"; then
110
+ MPV_ARGS+=(
111
+ "--demuxer-max-bytes=100MiB"
112
+ "--demuxer-max-back-bytes=50MiB"
113
+ "--cache=yes"
114
+ "--cache-secs=30"
115
+ )
116
+ fi
117
+
118
+ exec mpv "${MPV_ARGS[@]}"
119
+
120
+ # Fallback to ffplay
121
+ elif command -v ffplay &>/dev/null; then
122
+ echo "Playing with ffplay..."
123
+ FFPLAY_ARGS=(
124
+ -i "$STREAM_URL"
125
+ -window_title "BEX: $LABEL"
126
+ -loglevel warning
127
+ -autoexit
128
+ )
129
+
130
+ if [ -n "$MPV_HEADERS" ]; then
131
+ FFPLAY_ARGS+=(-headers "$MPV_HEADERS")
132
+ fi
133
+
134
+ exec ffplay "${FFPLAY_ARGS[@]}"
135
+
136
+ # Last resort: just print the URL for manual use
137
+ else
138
+ echo "No player found (mpv or ffplay required)"
139
+ echo ""
140
+ echo "Manual playback commands:"
141
+ echo ""
142
+ echo " mpv \"$STREAM_URL\" \\"
143
+ if [ -n "$MPV_HEADERS" ]; then
144
+ echo " --http-header-fields=\"${MPV_HEADERS}\" \\"
145
+ fi
146
+ echo " --cache=yes"
147
+ echo ""
148
+ echo " ffplay -i \"$STREAM_URL\" \\"
149
+ if [ -n "$MPV_HEADERS" ]; then
150
+ echo " -headers \"${MPV_HEADERS}\""
151
+ fi
152
+ echo ""
153
+ echo " curl -L -H 'User-Agent: Mozilla/5.0' \"$STREAM_URL\" | ffplay -"
154
+ exit 1
155
+ fi