Restream live videos (m3u8 and rtsp)

Hi all,

I’d like to pass a streamlink (copyright free) as query parameter to a view and give the content back to the player. I don’t want to use an iframe in the page.

Example:
the video player on the webpage has the following src url: https://djangosuperwebsite.com/streamview/?url=https://example.com/test.m3u8.

In my view I’d like to get the stream content of “url” and give it back to the player (on the fly).

It’s not clear to me how to achieve that. Could you please point me to the right direction?

Thanks in advance,

supermario18b

To clarify, in the Django view you want to open, read and then send out the content of the stream from the url querystring parameter?

If so, I think you could achieve that with the requests library’s Streaming Request feature and Django’s StreamingHttpResponse. However’s as the docs note in that section, Django is meant for short-lived requests. This proxying of a live stream may be better suited to a different language/framework.

1 Like

On top of Tim’s advice, I’ll also point out that what you’re trying to do is extremely “non-scalable”. If you’re just doing it for yourself and a couple other people, it may not be too bad. But trying to do this in double-digits number of users and you’re going to start encountering real issues.

1 Like

Thanks for the reply. Yes, that’s what I’d like to achieve. I’ve read the content you posted. Did you mean something like that?

def stream_content(request):
    #url_to_play is the url in the video player 
    url_to_play = request.GET.get("url")
    if url_to_play:
       return StreamingHttpResponse(get_stream_content(url_to_play))



def get_stream_content(url):
    r = requests.get(url, stream=True)

    for line in r.iter_lines():
        if line:
            yield line
            

I can see on the browser the m3u8 headers were received but the list with the chunk links is not there.

P.S. I’ve tried with a m3u8 link and a mp4 link

I’m sorry, I haven’t worked much with streaming responses. I won’t be able to help with the details here. Maybe someone else can chime in. Additionally, you may want to provide more specifics on what your experiencing.

1 Like

I’d make a guess that the data stream is not “line-oriented” data. I would expect them to be streaming blocks of binary data. You may have more success using iter_content instead.

2 Likes

Thank you @CodenameTim and @KenWhitesell, it works with iter_content.

supermario18b

If any one ever looks for an easy way here is how to show multiple streams in a django app

# views.py
def gen_frames(stream_url, stream_id):
    camera = cv2.VideoCapture(stream_url)
    ret, buffer = cv2.imencode('.jpg', frame)
    frame = buffer.tobytes()
    yield (b'--frame\r\n'
   b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

@csrf_exempt
def index(request):
    streams = Stream.objects.all()

    context = {
        'streams': streams,
    }
    return render(request, 'index.html', context)

@csrf_exempt
def video_feed(request, stream_id):
    stream = get_stream(stream_id)
    if stream.name == 'xyz':
        stream_url = f"rtsp://{username}:{password}@{ip_address}:554"

#models.py

class Stream(models.Model):
    username = models.CharField(max_length=100, blank=True)
    password = models.CharField(max_length=100, blank=True)
    ip_address = models.CharField(max_length=100, blank=True)
    stream_name = models.CharField(max_length=100, blank=True)
    

    def __str__(self):
        return self.stream_name

# html

<body style="background-color: black">
    <h1 style="color: crimson">Cameras</h1>
    <a href="{% url 'add_stream' %}">Add Camera</a>
 
    <div class="row mb-3 text-center">
    {% for camera in cameras %}
        <h2 style="color: crimson">{{ stream.stream_name }}</h2>
        <div class="col-6 themed-grid-col">.col-6</div>
        <img src="{% url 'video_feed' stream.id %}" width="640" height="480" />
        <div class="col-6 themed-grid-col">.col-6</div>
    {% endfor %}
    </div>
</body>

# urls

    path('', views.index, name='index'),
    path('video_feed/<int:stream_id>/', views.video_feed, name='video_feed'),