File size: 4,184 Bytes
2753d8f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/usr/bin/env bash
# Stream playback helper — takes BEX stream JSON output and plays with mpv/ffplay
#
# Usage:
#   ./play-stream.sh <stream_json>
#   echo '{"manifest_url":"...", "headers":[...]}' | ./play-stream.sh
#   ./play-stream.sh --from-file stream_output.json
#
# Supports:
#   - HLS (.m3u8) streams
#   - Direct MP4/MKV URLs
#   - Custom headers (Referer, User-Agent, etc.)
#   - mpv (preferred) or ffplay (fallback)
#
# The script extracts the stream URL and headers from the BEX engine's
# resolve-stream JSON output and constructs the correct player command.

set -euo pipefail

# Read JSON from stdin, argument, or file
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

# Parse JSON with jq (or python fallback)
if command -v jq &>/dev/null; then
    STREAM_URL=$(echo "$JSON" | jq -r '.manifest_url // .videos[0].url // empty')
    # Extract headers as key: value pairs
    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 ""

# Build header arguments
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 ""

# Try mpv first (best experience)
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

    # HLS-specific options
    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[@]}"

# Fallback to ffplay
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[@]}"

# Last resort: just print the URL for manual use
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