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

EsupPortail / Esup-Pod / 22356466754

24 Feb 2026 02:59PM UTC coverage: 68.113%. First build
22356466754

Pull #1403

github

web-flow
Merge 87799d05b 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

77.78
/pod/video_encode_transcript/encoding_utils.py
1
import json
1✔
2
import logging
1✔
3
import os
1✔
4
import shlex
1✔
5
import subprocess
1✔
6
from collections import OrderedDict
1✔
7
from timeit import default_timer as timer
1✔
8

9
try:
1✔
10
    from .encoding_settings import VIDEO_RENDITIONS
1✔
11
except (ImportError, ValueError):
×
12
    from encoding_settings import VIDEO_RENDITIONS
×
13

14
try:
1✔
15
    from django.conf import settings
1✔
16

17
    VIDEO_RENDITIONS = getattr(settings, "VIDEO_RENDITIONS", VIDEO_RENDITIONS)
1✔
18
    DEBUG = getattr(settings, "DEBUG", True)
1✔
19
except ImportError:  # pragma: no cover
20
    DEBUG = True
21

22
logger = logging.getLogger(__name__)
1✔
23
if DEBUG:
1✔
24
    logger.setLevel(logging.DEBUG)
1✔
25

26

27
def sec_to_timestamp(total_seconds) -> str:
1✔
28
    """Format time for webvtt caption."""
29
    if total_seconds < 0:
1✔
30
        total_seconds = 0
1✔
31
    hours = int(total_seconds // 3600)
1✔
32
    minutes = int((total_seconds % 3600) // 60)
1✔
33
    seconds = total_seconds % 60
1✔
34
    return "{:02d}:{:02d}:{:06.3f}".format(hours, minutes, seconds)
1✔
35

36

37
def get_dressing_position_value(position: str, height: str) -> str:
1✔
38
    """
39
    Obtain dimensions proportional to the video format.
40

41
    Args:
42
        position (str): property "position" of the dressing object.
43
        height (str): height of the source video.
44

45
    Returns:
46
        str: params for the ffmpeg command.
47
    """
48
    height = str(float(height) * 0.05)
1✔
49
    if position == "top_right":
1✔
50
        return "overlay=main_w-overlay_w-" + height + ":" + height
1✔
51
    elif position == "top_left":
1✔
52
        return "overlay=" + height + ":" + height
1✔
53
    elif position == "bottom_right":
1✔
54
        return "overlay=main_w-overlay_w-" + height + ":main_h-overlay_h-" + height
1✔
55
    elif position == "bottom_left":
1✔
56
        return "overlay=" + height + ":main_h-overlay_h-" + height
1✔
NEW
57
    return ""
×
58

59

60
def get_renditions():
1✔
61
    try:
1✔
62
        from django.core import serializers
1✔
63

64
        from .models import VideoRendition
1✔
65

66
        renditions = json.loads(
1✔
67
            serializers.serialize("json", VideoRendition.objects.all())
68
        )
69
        video_rendition = []
1✔
70
        for rend in renditions:
1✔
71
            video_rendition.append(rend["fields"])
1✔
72
        return video_rendition
1✔
73
    except ImportError:
×
74
        return VIDEO_RENDITIONS
×
75

76

77
def check_file(path_file) -> bool:
1✔
78
    if os.access(path_file, os.F_OK) and os.stat(path_file).st_size > 0:
1✔
79
        return True
1✔
80
    return False
1✔
81

82

83
def get_list_rendition():
1✔
84
    list_rendition = {}
1✔
85
    renditions = get_renditions()
1✔
86
    for rend in renditions:
1✔
87
        list_rendition[int(rend["resolution"].split("x")[1])] = rend
1✔
88
    list_rendition = OrderedDict(sorted(list_rendition.items(), key=lambda t: t[0]))
1✔
89
    return list_rendition
1✔
90

91

92
def get_info_from_video(probe_cmd):
1✔
93
    info = None
1✔
94
    msg = ""
1✔
95
    try:
1✔
96
        output = subprocess.check_output(shlex.split(probe_cmd), stderr=subprocess.PIPE)
1✔
97
        info = json.loads(output)
1✔
98
    except subprocess.CalledProcessError as e:
×
99
        # raise RuntimeError('ffprobe returned non-zero status: {}'.format(
100
        # e.stderr))
101
        msg += 20 * "////" + "\n"
×
102
        msg += "Runtime Error: {0}\n".format(e)
×
103
    except OSError as err:
×
104
        # raise OSError(e.errno, 'ffprobe not found: {}'.format(e.strerror))
105
        msg += 20 * "////" + "\n"
×
106
        msg += "OS error: {0}\n".format(err)
×
107
    return info, msg
1✔
108

109

110
def launch_cmd(cmd):
1✔
111
    if cmd == "":
1✔
112
        msg = "No cmd to launch"
×
113
        logger.warning(msg)
×
114
        return False, msg
×
115
    msg = ""
1✔
116
    encode_start = timer()
1✔
117
    return_value = False
1✔
118
    try:
1✔
119
        logger.debug("launch_cmd: %s" % cmd)
1✔
120
        output = subprocess.run(
1✔
121
            shlex.split(cmd),
122
            stdout=subprocess.PIPE,
123
            stderr=subprocess.STDOUT,
124
        )
125
        encode_end = timer() - encode_start
1✔
126
        msg += cmd + "\n"
1✔
127
        msg += "Encode file in {:.3}s.\n".format(encode_end)
1✔
128
        # msg += "\n".join(output.stdout.decode().split('\n'))
129
        try:
1✔
130
            msg += output.stdout.decode("utf-8")
1✔
131
        except UnicodeDecodeError:
×
132
            pass
×
133
        msg += "\n"
1✔
134
        if output.returncode != 0:
1✔
135
            msg += "ERROR RETURN CODE %s for command %s" % (output.returncode, cmd)
×
136
        else:
137
            return_value = True
1✔
138
    except (subprocess.CalledProcessError, OSError) as e:
×
139
        # raise RuntimeError('ffmpeg returned non-zero status: {}'.format(
140
        # e.stderr))
141
        msg += 20 * "////" + "\n"
×
142
        err_msg = "Runtime or OS Error: {0}\n".format(e)
×
143
        msg += err_msg
×
144
        logger.error(err_msg)
×
145
    return return_value, msg
1✔
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