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

EsupPortail / Esup-Pod / 5462629459

pending completion
5462629459

Pull #899

github

web-flow
Merge e759dacb6 into c94f0e331
Pull Request #899: [DONE] Ptitloup/feature new encoding

400 of 400 new or added lines in 14 files covered. (100.0%)

8968 of 12675 relevant lines covered (70.75%)

0.71 hits per line

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

23.26
/pod/video_encode_transcript/encoding_studio.py
1
"""This module handles studio encoding with CPU."""
2
from django.conf import settings
1✔
3
from .utils import check_file, send_email_recording
1✔
4
from . import encode
1✔
5

6
import time
1✔
7
import subprocess
1✔
8
import json
1✔
9

10
from .encoding_settings import (
1✔
11
    FFMPEG_CMD,
12
    FFPROBE_CMD,
13
    FFMPEG_CRF,
14
    FFMPEG_NB_THREADS,
15
    FFPROBE_GET_INFO,
16
    FFMPEG_STUDIO_COMMAND,
17
)
18

19
FFMPEG_CMD = getattr(settings, "FFMPEG_CMD", FFMPEG_CMD)
1✔
20
FFPROBE_CMD = getattr(settings, "FFPROBE_CMD", FFPROBE_CMD)
1✔
21
FFMPEG_CRF = getattr(settings, "FFMPEG_CRF", FFMPEG_CRF)
1✔
22
FFMPEG_NB_THREADS = getattr(settings, "FFMPEG_NB_THREADS", FFMPEG_NB_THREADS)
1✔
23
FFPROBE_GET_INFO = getattr(settings, "FFPROBE_GET_INFO", FFPROBE_GET_INFO)
1✔
24
FFMPEG_STUDIO_COMMAND = getattr(settings, "FFMPEG_STUDIO_COMMAND", FFMPEG_STUDIO_COMMAND)
1✔
25

26
DEBUG = getattr(settings, "DEBUG", True)
1✔
27

28
ENCODE_VIDEO = getattr(settings, "ENCODE_VIDEO", "start_encode")
1✔
29

30
# ##########################################################################
31
# ENCODE VIDEO STUDIO: MAIN ENCODE
32
# ##########################################################################
33

34

35
def get_video_info(command):
1✔
36
    """Get ffprobe video info."""
37
    ffproberesult = subprocess.run(
×
38
        command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
39
    )
40
    return json.loads(ffproberesult.stdout.decode("utf-8"))
×
41

42

43
def encode_video_studio(recording_id, video_output, videos, subtime, presenter):
1✔
44
    """Encode video from studio."""
45
    presenter_source = None
×
46
    presentation_source = None
×
47
    input_video = ""
×
48
    for video in videos:
×
49
        if video.get("type") == "presenter/source":
×
50
            presenter_source = video.get("src")
×
51
            input_video = '-i "' + presenter_source + '" '
×
52
        if video.get("type") == "presentation/source":
×
53
            presentation_source = video.get("src")
×
54
            input_video = '-i "' + presentation_source + '" '
×
55
    info_presenter_video = {}
×
56
    info_presentation_video = {}
×
57
    if presenter_source and presentation_source:
×
58
        # to put it in the right order
59
        input_video = '-i "' + presentation_source + '" -i "' + presenter_source + '" '
×
60
        command = FFPROBE_GET_INFO % {
×
61
            "ffprobe": FFPROBE_CMD,
62
            "select_streams": "-select_streams v:0 ",
63
            "source": '"' + presentation_source + '" ',
64
        }
65
        info_presentation_video = get_video_info(command)
×
66
        command = FFPROBE_GET_INFO % {
×
67
            "ffprobe": FFPROBE_CMD,
68
            "select_streams": "-select_streams v:0 ",
69
            "source": '"' + presenter_source + '" ',
70
        }
71
        info_presenter_video = get_video_info(command)
×
72
        subcmd = get_sub_cmd(
×
73
            get_height(info_presentation_video),
74
            get_height(info_presenter_video),
75
            presenter,
76
        )
77

78
    else:
79
        subcmd = " -vsync 0 "
×
80
    subcmd += " -movflags +faststart -f mp4 "
×
81

82
    msg = launch_encode_video_studio(input_video, subtime, subcmd, video_output)
×
83
    from pod.recorder.models import Recording
×
84

85
    recording = Recording.objects.get(id=recording_id)
×
86
    recording.comment += msg
×
87
    recording.save()
×
88
    if check_file(video_output):
×
89
        from pod.recorder.plugins.type_studio import save_basic_video
×
90
        video = save_basic_video(recording, video_output)
×
91
        encode_video = getattr(encode, ENCODE_VIDEO)
×
92
        encode_video(video.id, False)
×
93
    else:
94
        msg = "Wrong file or path:" + "\n%s" % video_output
×
95
        send_email_recording(msg, recording_id)
×
96

97

98
def get_sub_cmd(height_presentation_video, height_presenter_video, presenter):
1✔
99
    min_height = min([height_presentation_video, height_presenter_video])
×
100
    subcmd = ""
×
101
    if presenter == "pipb":
×
102
        # trouver la bonne hauteur en fonction de la video de presentation
103
        height = (
×
104
            height_presentation_video
105
            if (height_presentation_video % 2) == 0
106
            else height_presentation_video + 1
107
        )
108
        # ffmpeg -y -i presentation_source.webm -i presenter_source.webm \
109
        # -c:v libx264 -filter_complex "[0:v]scale=-2:720[pres];[1:v]scale=-2:180[pip];\
110
        # [pres][pip]overlay=W-w-10:H-h-10:shortest=1" \
111
        # -vsync 0 outputVideo.mp4
112
        subcmd = (
×
113
            " -filter_complex "
114
            + '"[0:v]scale=-2:%(height)s[pres];[1:v]scale=-2:%(sh)s[pip];'
115
            % {"height": height, "sh": height / 4}
116
            + '[pres][pip]overlay=W-w-10:H-h-10:shortest=1" -vsync 0 '
117
        )
118
    if presenter == "piph":
×
119
        # trouver la bonne hauteur en fonction de la video de presentation
120
        height = (
×
121
            height_presentation_video
122
            if (height_presentation_video % 2) == 0
123
            else height_presentation_video + 1
124
        )
125
        # ffmpeg -y -i presentation_source.webm -i presenter_source.webm \
126
        # -c:v libx264 -filter_complex "[0:v]scale=-2:720[pres];[1:v]scale=-2:180[pip];\
127
        # [pres][pip]overlay=W-w-10:H-h-10:shortest=1" \
128
        # -vsync 0 outputVideo.mp4
129
        subcmd = (
×
130
            " -filter_complex "
131
            + '"[0:v]scale=-2:%(height)s[pres];[1:v]scale=-2:%(sh)s[pip];'
132
            % {"height": height, "sh": height / 4}
133
            + '[pres][pip]overlay=W-w-10:10:shortest=1" -vsync 0 '
134
        )
135
    if presenter == "mid":
×
136
        height = min_height if (min_height % 2) == 0 else min_height + 1
×
137
        # ffmpeg -i presentation.webm -i presenter.webm \
138
        # -c:v libx264 -filter_complex "[0:v]scale=-2:720[left];[left][1:v]hstack" \
139
        # outputVideo.mp4
140
        subcmd = (
×
141
            " -filter_complex "
142
            + '"[0:v]scale=-2:%(height)s[left];[1:v]scale=-2:%(height)s[right];'
143
            % {"height": height}
144
            + '[left][right]hstack" -vsync 0 '
145
        )
146

147
    return subcmd
×
148

149

150
def get_height(info):
1✔
151
    """Get the height value from the given video information dictionary."""
152
    in_height = 0
×
153
    if len(info["streams"]) > 0 and info["streams"][0].get("height"):
×
154
        in_height = info["streams"][0]["height"]
×
155
    return in_height
×
156

157

158
def launch_encode_video_studio(input_video, subtime, subcmd, video_output):
1✔
159
    """Encode video for studio."""
160
    msg = ""
×
161
    partial_command = FFMPEG_STUDIO_COMMAND % {
×
162
        "nb_threads": FFMPEG_NB_THREADS,
163
        "input": input_video,
164
        "subtime": subtime,
165
        "crf": FFMPEG_CRF,
166
    }
167
    ffmpegStudioCommand = "%s %s %s %s" % (
×
168
        FFMPEG_CMD,
169
        partial_command,
170
        subcmd,
171
        video_output,
172
    )
173
    msg += "- %s\n" % ffmpegStudioCommand
×
174
    logfile = video_output.replace(".mp4", ".log")
×
175
    ffmpegstudio = subprocess.run(
×
176
        ffmpegStudioCommand, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
177
    )
178
    with open(logfile, "ab") as f:
×
179
        f.write(b"\n\ffmpegstudio:\n\n")
×
180
        f.write(ffmpegstudio.stdout)
×
181
    msg += "\n- Encoding Mp4: %s" % time.ctime()
×
182
    if DEBUG:
×
183
        print(msg)
×
184
        print(ffmpegstudio.stdout)
×
185
        print(ffmpegstudio.stderr)
×
186
    return msg
×
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