使用来自 jellyfin 的 django 进行视频流传输

问题描述 投票:0回答:1

我用 jellyfin 服务器上的 django 制作了一个 streaming 应用程序,我使用视频 js 来播放我的视频媒体。问题是,当我尝试播放超过 1 小时且更长的视频时,会花费疯狂的时间,似乎视频是先下载然后播放的,而且我无法推进媒体并将其放在我的位置想,我首先怀疑有一个名为 preloadvideo js 选项,所以我尝试了值 'none','metadata''auto',但没有任何结果实际上,一位同事给了我一个猜测也许 django 不支持这种功能!谁能证实这一点吗? django 的解决方案是什么?

例如,这是我获取剧集类型电影的功能:

views.py

def episode_detail(request, episode_id): user_id = request.session.get('jellyfin_user_id') access_token = request.session.get('jellyfin_access_token') if not user_id or not access_token: return redirect('jellyfin_login') # try: # user = JellyfinUser.objects.get(jellyfin_user_id=user_id) # except JellyfinUser.DoesNotExist: # return redirect('jellyfin_login') headers = { 'X-Emby-Token': settings.JELLYFIN_API_KEY } episode_url = f"{settings.JELLYFIN_URL}/Users/{user_id}/Items/{episode_id}" episode_response = requests.get(episode_url, headers=headers) if episode_response.status_code != 200: return render(request, 'error.html', context={'error': 'Unable to fetch episode details'}) episode = episode_response.json() if episode['Type'] == 'Movie': people = episode.get('People', []) if people is None: people = [] genres_url = f"{settings.JELLYFIN_URL}/Genres?ParentId={episode_id}" genres_response = requests.get(genres_url, headers=headers) genres = genres_response.json().get('Items', []) if genres_response.status_code == 200 else [] episode['Genres'] = [genre['Name'] for genre in genres] studio_url = f"{settings.JELLYFIN_URL}/Studios?ParentId={episode_id}" studio_response = requests.get(studio_url, headers=headers) studios = studio_response.json().get('Items', []) if studio_response.status_code == 200 else [] episode['Studios'] = [studio['Name'] for studio in studios] directors = [person['Name'] for person in people if person['Type'] == 'Director'] episode['Directors'] = directors actors = [] for person in people: if person['Type'] == 'Actor': actor_image_url = f"{settings.JELLYFIN_URL}/Persons/{person['Name']}/Images/Primary" actor_image_url_response = requests.get(actor_image_url, headers=headers) if actor_image_url_response.status_code == 200: person['ImageURL'] = actor_image_url else: person['ImageURL'] = static("library/images/default/default-user.jpg") actor_info = { 'name': person['Name'], 'role': person['Role'], 'image': person['ImageURL'], 'id': person['Id'], } actors.append(actor_info) episode['Actors'] = actors writers = [person['Name'] for person in people if person['Type'] == 'Writer'] episode['Writers'] = writers producers = [person['Name'] for person in people if person['Type'] == 'Producer'] episode['Producers'] = producers similar_url = f"{settings.JELLYFIN_URL}/Items/{episode_id}/Similar" similar_response = requests.get(similar_url, headers=headers) similar_episodes = similar_response.json().get('Items', []) if similar_response.status_code == 200 else [] for item in similar_episodes: item['ImageURL'] = f"{settings.JELLYFIN_URL}/Items/{item['Id']}/Images/Primary" episode['SimilarEpisodes'] = similar_episodes episode['VideoURL'] = f"{settings.JELLYFIN_URL}/Videos/{episode['Id']}/stream" episode['ImageURL'] = f"{settings.JELLYFIN_URL}/Items/{episode['Id']}/Images/Primary" episode['BackdropURL'] = f"{settings.JELLYFIN_URL}/Items/{episode['Id']}/Images/Backdrop" episode['CommunityRating'] = episode.get('CommunityRating', 'N/A') episode['Overview'] = episode.get('Overview', 'Aucune description disponible') episode['Duration'] = format_duration(episode['RunTimeTicks']) print("NO FILE") user_data = episode.get('UserData', {}) if user_data is None: user_data = {} episode['IsFavorite'] = user_data.get('IsFavorite', False) print(episode['Type']) return render(request, 'episode_detail.html', context={'episode': episode})
这是我的 Episode_detail.html:

episode_detail.html

{% extends 'base.html' %} {% block title %} {{ episode.Name }} {% endblock %} {% block style %} <!-- My Styles --> {% endblock %} {% block content %} <div class="container mb-5"> {% if episode.Type == 'Movie' %} <div class="row"> <!-- AFFICHE DU FILM --> <div class="col-md-4"> <img src="{{ episode.ImageURL }}" class="img-fluid movie-poster shadow-lg" alt="{{ episode.Name }}"> </div> <!-- INFOS DU FILM --> <div class="col-md-8"> <h1 class="text-white">{{ episode.Name }}</h1> <div class="d-flex align-items-center"> <span class="production-year">{{ episode.ProductionYear }}</span> <span class="duration">{{ episode.Duration }}</span> <span class="note-commu"> <span>{{ episode.CommunityRating|floatformat:1 }}</span> <span class="blue-star"><i class="fa-solid fa-star"></i></span> </span> </div> <!-- SYNOPSIS DU FILM --> {% if episode.Overview %} <div class="mt-3"> <h4 class="section-title"><b>Synopsis</b></h4> <p>{{ episode.Overview }}</p> </div> {% endif %} <!-- DETAILS DU FILM --> <div class="mt-3"> {% if episode.Genres or episode.Studios or episode.Directors or episode.Actors %} <h4 class="section-title"><b>Details</b></h4> {% endif %} {% if episode.Genres %}<p><strong>Genre:</strong> {{ episode.Genres|join:", " }}</p>{% endif %} {% if episode.Studios %}<p><strong>Studios:</strong> {{ episode.Studios|join:", " }}</p>{% endif %} {% if episode.Directors %}<p><strong>Réalisateurs :</strong> {{episode.Directors|join:", " }}</p>{% endif %} {% if episode.Writers %}<p><strong>Scénaristes :</strong> {{episode.Writers|join:", " }}</p>{% endif %} {% if episode.Producers %}<p><strong>Producteurs:</strong> {{ episode.Producers|join:", " }}</p>{% endif %} {% if episode.Actors_name %}<p><strong>Acteurs:</strong> {{ episode.Actors_name|join:", " }}</p>{% endif %} </div> <!-- SECTION VIDEO DU FILM --> <div class="mt-5"> <video id="my-movie-video" class="video-js vjs-big-play-centered vjs-fluid vjs-fill" controls preload="none" poster="{{ episode.BackdropURL }}" data-setup="{}" > <source src="{{ episode.VideoURL }}" type="video/mp4" /> <source src="{{ episode.VideoURL }}" type="video/webm" /> <source src="{{ episode.VideoURL }}" type="video/avi" /> <source src="{{ episode.VideoURL }}" type="video/mkv" /> <p class="vjs-no-js"> To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a> </p> </video> </div> </div> </div> </div> {% endblock %}
    
django video-streaming html5-video video.js
1个回答
0
投票

“似乎视频先下载然后播放需要疯狂的时间”

检查您的 MP4 的元数据是否位于前面(而不是文件的后面)。

您可以使用
此站点 检查 MP4(向下滚动到 MP4 原子位置 部分)。 如果它显示
“未优化”,则元数据位于后面(并且还需要完整下载)。

您可以使用 FFmpeg 等工具进行修复,甚至可以在 Google 中搜索:

MP4 moov 快速启动修复建议。

“我无法将介质推进并放到我想要的位置,””

当您自己提供字节(通过流式传输)时,您必须自己处理查找。

这意味着监听
seek 事件(由 HTML5 视频标签触发)并为该查找点提供新字节。您的 MP4 必须是碎片 MP4才能通过字节流轻松查找。当您的应用程序获得一个搜索点(以秒为单位)时,您将计算需要读取哪个文件(如果按时间分隔)或哪个字节范围(如果所有视频持续时间都在一个文件内)。您的流媒体现在改为发送这些字节。这些字节将是一个 MP4 片段,表示请求的“查找”时间的数据。

© www.soinside.com 2019 - 2024. All rights reserved.