-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathvideo_upload.py
More file actions
141 lines (106 loc) · 4.04 KB
/
video_upload.py
File metadata and controls
141 lines (106 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
from dataclasses import dataclass
from notifications.template_utils import render_template_from_string
import cv2
from django.core.files.base import ContentFile
from django.core.files.storage import storages
from schedule.models import ScheduleItem
@dataclass
class VideoInfo:
title: str
description: str
tags: list[str]
@property
def tags_as_str(self) -> str:
return ",".join(self.tags)
def create_video_info(schedule_item: ScheduleItem) -> VideoInfo:
all_speakers = schedule_item.speakers
count_speakers = len(all_speakers)
speakers_names = ", ".join([speaker.fullname for speaker in all_speakers])
tags = [
clean_tag(tag)
for tag in (
schedule_item.submission.tags.values_list("name", flat=True)
if schedule_item.submission_id
else []
)
]
context = {
"has_speakers": count_speakers > 0,
"has_more_than_2_speakers": count_speakers > 2,
"has_zero_or_more_than_2_speakers": count_speakers == 0 or count_speakers > 2,
"count_speakers": count_speakers,
"speakers_names": speakers_names,
"title": schedule_item.title,
"abstract": schedule_item.abstract,
"slug": schedule_item.slug,
"elevator_pitch": schedule_item.elevator_pitch,
"conference_name": schedule_item.conference.name,
"hashtags": " ".join([f"#{tag}" for tag in tags]),
}
title = render_template_from_string(
schedule_item.conference.video_title_template, context
)
if len(title) > 100:
title = schedule_item.title
description = render_template_from_string(
schedule_item.conference.video_description_template, context
)
return VideoInfo(
title=replace_invalid_chars_with_lookalikes(title),
description=replace_invalid_chars_with_lookalikes(description),
tags=tags,
)
def download_video_file(id: int, path: str) -> str:
video_storage = storages["default"]
local_storage = storages["localstorage"]
filename = get_video_file_name(id)
if not local_storage.exists(filename):
local_storage.save(filename, video_storage.open(path))
return local_storage.path(filename)
def extract_video_thumbnail(remote_video_path: str, id: int) -> str:
local_storage = storages["localstorage"]
thumbnail_file_name = get_thumbnail_file_name(id)
file_path = local_storage.path(thumbnail_file_name)
if local_storage.exists(thumbnail_file_name):
return file_path
local_video_path = download_video_file(id, remote_video_path)
video_capture = cv2.VideoCapture(local_video_path)
success, image = video_capture.read()
if not success:
raise ValueError("Unable to extract frame")
ret, buffer = cv2.imencode(".jpg", image)
if not ret:
raise ValueError("Unable to encode frame")
content_file = ContentFile(buffer.tobytes())
local_storage.save(thumbnail_file_name, content_file)
return local_storage.path(thumbnail_file_name)
def cleanup_local_files(id: int, delete_thumbnail: bool = True):
local_storage = storages["localstorage"]
thumbnail_file_name = get_thumbnail_file_name(id)
if delete_thumbnail and local_storage.exists(thumbnail_file_name):
local_storage.delete(thumbnail_file_name)
video_file_name = get_video_file_name(id)
if local_storage.exists(video_file_name):
local_storage.delete(video_file_name)
def get_thumbnail_file_name(id: int) -> str:
return f"{id}-thumbnail.jpg"
def get_video_file_name(id: int) -> str:
return f"{id}-video_upload"
def replace_invalid_chars_with_lookalikes(text: str) -> str:
homoglyphs = {
"<": "\u1438",
">": "\u1433",
}
for char, homoglyph in homoglyphs.items():
text = text.replace(char, homoglyph)
return text.replace("\n\n\n", "\n\n")
def clean_tag(tag: str) -> str:
return (
tag.strip()
.replace(" ", "")
.replace("-", "")
.replace(".", "")
.replace("/", "")
.replace("(", "")
.replace(")", "")
)