• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

EsupPortail / Esup-Pod / 22358373981

24 Feb 2026 03:47PM UTC coverage: 68.113%. First build
22358373981

Pull #1403

github

web-flow
Merge 9b6420310 into 7506dd15c
Pull Request #1403: Runner Manager support

632 of 1453 new or added lines in 24 files covered. (43.5%)

12812 of 18810 relevant lines covered (68.11%)

0.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.38
/pod/video_encode_transcript/rest_views.py
1
import json
1✔
2
import logging
1✔
3
import os
1✔
4

5
import webvtt
1✔
6
from django.conf import settings
1✔
7
from django.core.exceptions import SuspiciousOperation
1✔
8
from django.shortcuts import get_object_or_404
1✔
9
from django.views.decorators.csrf import csrf_exempt
1✔
10
from rest_framework import serializers, viewsets
1✔
11
from rest_framework.decorators import action, api_view
1✔
12
from rest_framework.response import Response
1✔
13

14
from pod.recorder.models import Recording
1✔
15
from pod.video.models import Video
1✔
16
from pod.video.rest_views import VideoSerializer
1✔
17

18
from .models import EncodingAudio, EncodingVideo, PlaylistVideo, VideoRendition
1✔
19

20
USE_TRANSCRIPTION = getattr(settings, "USE_TRANSCRIPTION", False)
1✔
21
if USE_TRANSCRIPTION:
1✔
22
    from pod.video_encode_transcript.transcript import start_transcript
1✔
23

24
MEDIA_ROOT = getattr(settings, "MEDIA_ROOT", "")
1✔
25

26
DEBUG = getattr(settings, "DEBUG", True)
1✔
27
logger = logging.getLogger(__name__)
1✔
28
if DEBUG:
1✔
29
    logger.setLevel(logging.DEBUG)
1✔
30

31

32
class VideoRenditionSerializer(serializers.HyperlinkedModelSerializer):
1✔
33
    class Meta:
1✔
34
        model = VideoRendition
1✔
35
        fields = (
1✔
36
            "id",
37
            "url",
38
            "resolution",
39
            "video_bitrate",
40
            "audio_bitrate",
41
            "encode_mp4",
42
            "sites",
43
        )
44

45

46
class EncodingVideoSerializer(serializers.HyperlinkedModelSerializer):
1✔
47
    """Serializer for the EncodingVideo model."""
48

49
    class Meta:
1✔
50
        model = EncodingVideo
1✔
51
        fields = (
1✔
52
            "id",
53
            "url",
54
            "name",
55
            "video",
56
            "rendition",
57
            "encoding_format",
58
            "source_file",
59
            "sites_all",
60
        )
61

62

63
class EncodingAudioSerializer(serializers.HyperlinkedModelSerializer):
1✔
64
    """Serializer for the EncodingAudio model."""
65

66
    class Meta:
1✔
67
        model = EncodingAudio
1✔
68
        fields = (
1✔
69
            "id",
70
            "url",
71
            "name",
72
            "video",
73
            "encoding_format",
74
            "source_file",
75
            "sites_all",
76
        )
77

78

79
class EncodingVideoViewSet(viewsets.ModelViewSet):
1✔
80
    """Viewset for EncodingVideo model."""
81

82
    queryset = EncodingVideo.objects.all()
1✔
83
    serializer_class = EncodingVideoSerializer
1✔
84
    filterset_fields = [
1✔
85
        "video",
86
    ]
87

88
    @action(detail=False, methods=["get"])
1✔
89
    def video_encodedfiles(self, request):
1✔
90
        """Retrieve encoded video files."""
91
        encoded_videos = EncodingVideoViewSet.filter_encoded_medias(
×
92
            self.queryset, request
93
        )
94
        encoded_videos = sorted(encoded_videos, key=lambda x: x.height)
×
95
        serializer = EncodingVideoSerializer(
×
96
            encoded_videos, many=True, context={"request": request}
97
        )
98
        return Response(serializer.data)
×
99

100
    @staticmethod
1✔
101
    def filter_encoded_medias(queryset, request):
1✔
102
        """Filter encoded media files."""
103
        encoded_audios = queryset
×
104
        if request.GET.get("video"):
×
105
            encoded_audios = encoded_audios.filter(video__id=request.GET.get("video"))
×
106
        if request.GET.get("extension"):
×
107
            encoded_audios = encoded_audios.filter(
×
108
                source_file__iendswith=request.GET.get("extension")
109
            )
110
        return encoded_audios
×
111

112

113
class EncodingAudioViewSet(viewsets.ModelViewSet):
1✔
114
    """Viewset for EncodingAudio model."""
115

116
    queryset = EncodingAudio.objects.all()
1✔
117
    serializer_class = EncodingAudioSerializer
1✔
118
    filterset_fields = [
1✔
119
        "video",
120
    ]
121

122
    @action(detail=False, methods=["get"])
1✔
123
    def audio_encodedfiles(self, request):
1✔
124
        """Retrieve encoded audio files."""
125
        encoded_audios = EncodingVideoViewSet.filter_encoded_medias(
×
126
            self.queryset, request
127
        )
128
        serializer = EncodingAudioSerializer(
×
129
            encoded_audios, many=True, context={"request": request}
130
        )
131
        return Response(serializer.data)
×
132

133

134
class VideoRenditionViewSet(viewsets.ModelViewSet):
1✔
135
    queryset = VideoRendition.objects.all()
1✔
136
    serializer_class = VideoRenditionSerializer
1✔
137

138

139
class PlaylistVideoSerializer(serializers.HyperlinkedModelSerializer):
1✔
140
    class Meta:
1✔
141
        model = PlaylistVideo
1✔
142
        fields = (
1✔
143
            "id",
144
            "url",
145
            "name",
146
            "video",
147
            "encoding_format",
148
            "source_file",
149
            "sites_all",
150
        )
151

152

153
class PlaylistVideoViewSet(viewsets.ModelViewSet):
1✔
154
    queryset = PlaylistVideo.objects.all()
1✔
155
    serializer_class = PlaylistVideoSerializer
1✔
156

157

158
@api_view(["GET"])
1✔
159
def launch_encode_view(request):
1✔
160
    """View API for launching video encoding."""
161
    video = get_object_or_404(Video, slug=request.GET.get("slug"))
×
162
    if (
×
163
        video is not None
164
        and (
165
            not hasattr(video, "launch_encode")
166
            or getattr(video, "launch_encode") is True
167
        )
168
        and video.encoding_in_progress is False
169
    ):
170
        video.launch_encode = True
×
171
        video.save()
×
172
    return Response(VideoSerializer(instance=video, context={"request": request}).data)
×
173

174

175
@api_view(["GET"])
1✔
176
def launch_transcript_view(request):
1✔
177
    """View API for launching transcript."""
178
    video = get_object_or_404(Video, slug=request.GET.get("slug"))
×
179
    if video is not None and video.get_video_mp3():
×
180
        start_transcript(video.id, threaded=True)
×
181
    return Response(VideoSerializer(instance=video, context={"request": request}).data)
×
182

183

184
@csrf_exempt
1✔
185
@api_view(["POST"])
1✔
186
def store_remote_encoded_video(request):
1✔
187
    """View API for storing remote encoded videos."""
NEW
188
    from .encode import end_of_encoding, store_encoding_info
×
189
    from .Encoding_video_model import Encoding_video_model
×
190

191
    video_id = request.GET.get("id", 0)
×
192
    logger.info("Start importing encoding data for video: %s" % video_id)
×
193
    video = get_object_or_404(Video, id=video_id)
×
194
    # start_store_remote_encoding_video(video_id)
195
    # check if video is encoding!!!
196
    data = json.loads(request.body.decode("utf-8"))
×
197
    if video.encoding_in_progress is False:
×
198
        raise SuspiciousOperation("Video not being encoded.")
×
199
    if str(video_id) != str(data["video_id"]):
×
200
        raise SuspiciousOperation(
×
201
            "Different video id: %s - %s" % (video_id, data["video_id"])
202
        )
203
    encoding_video = Encoding_video_model(
×
204
        video_id, data["video_path"], data["cut_start"], data["cut_end"]
205
    )
206
    encoding_video.start = data["start"]
×
207
    encoding_video.stop = data["stop"]
×
208
    final_video = store_encoding_info(video_id, encoding_video)
×
209
    end_of_encoding(final_video)
×
210
    return Response(VideoSerializer(instance=video, context={"request": request}).data)
×
211

212

213
@csrf_exempt
1✔
214
@api_view(["POST"])
1✔
215
def store_remote_encoded_video_studio(request):
1✔
216
    from .encode import store_encoding_studio_info
×
217

218
    recording_id = request.GET.get("recording_id", 0)
×
219
    get_object_or_404(Recording, id=recording_id)
×
220
    data = json.loads(request.body.decode("utf-8"))
×
221
    store_encoding_studio_info(recording_id, data["video_output"], data["msg"])
×
222
    return Response("ok")
×
223

224

225
@csrf_exempt
1✔
226
@api_view(["POST"])
1✔
227
def store_remote_transcripted_video(request):
1✔
228
    """View API for storing remote transcripted videos."""
229
    from .transcript import save_vtt_and_notify
×
230

231
    video_id = request.GET.get("id", 0)
×
232
    video = get_object_or_404(Video, id=video_id)
×
233
    # check if video is encoding!!!
234
    data = json.loads(request.body.decode("utf-8"))
×
235
    if str(video_id) != str(data["video_id"]):
×
236
        raise SuspiciousOperation(
×
237
            "different video id: %s - %s" % (video_id, data["video_id"])
238
        )
239
    logger.info("Start importing transcription data for video: %s" % video_id)
×
240
    filename = os.path.basename(data["temp_vtt_file"])
×
241
    media_temp_dir = os.path.join(MEDIA_ROOT, "temp")
×
242
    filepath = os.path.join(media_temp_dir, filename)
×
243
    new_vtt = webvtt.read(filepath)
×
244
    save_vtt_and_notify(video, data["msg"], new_vtt)
×
245
    os.remove(filepath)
×
246
    return Response(VideoSerializer(instance=video, context={"request": request}).data)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc