yearye commited on
Commit
2f461c2
ยท
verified ยท
1 Parent(s): fea8200

Upload 5 files

Browse files
features.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:499398a910ad766c26ea73fe5efaf6f71da2990d16d4f8e05740ab37b00de7a6
3
+ size 108
label_encoders.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:56634bf5e292b2396763f85be2cc6b46d28a2f2ceefcdef99dbe00f60e06901e
3
+ size 636
predict_module.py ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ import requests
4
+ import cv2
5
+ import mediapipe as mp
6
+ import torch
7
+ from PIL import Image
8
+ from io import BytesIO
9
+ from joblib import load
10
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
11
+ from youtube_transcript_api import YouTubeTranscriptApi
12
+
13
+ # ๋ชจ๋ธ ๋ฐ ๊ธฐํƒ€ ํŒŒ์ผ ๋กœ๋“œ
14
+ model = load('model/view_predictor.joblib')
15
+ _, _, le_cat = load('model/label_encoders.joblib')
16
+ feature_cols = load('model/features.joblib')
17
+
18
+ # ๊ฐ์„ฑ ๋ถ„์„ ๋ชจ๋ธ
19
+ senti_model_name = "nlp04/korean_sentiment_analysis_kcelectra"
20
+ senti_tokenizer = AutoTokenizer.from_pretrained(senti_model_name)
21
+ senti_model = AutoModelForSequenceClassification.from_pretrained(senti_model_name)
22
+ senti_model.eval()
23
+
24
+ def sentiment_score(text):
25
+ if not text or pd.isna(text):
26
+ return 0.0
27
+ with torch.no_grad():
28
+ inputs = senti_tokenizer(text, return_tensors="pt", truncation=True)
29
+ outputs = senti_model(**inputs)
30
+ probs = torch.softmax(outputs.logits, dim=1).squeeze()
31
+ try:
32
+ return round(float(probs[2]) * 100, 1) # Positive
33
+ except IndexError:
34
+ return round(float(probs[1]) * 100, 1)
35
+
36
+ category_dict = {
37
+ '์Œ์‹': ['์ฏ”์–‘', '์ฐจ๋ฐฅ์—ด๋ผ', '๋จน๋ฐฉ', '๋‹จ๊ณจ', '์•„์นจ', '์žฅ์‚ฌ', '๋งŒ๋“ค๊ธฐ', '์นผ๋กœ๋ฆฌ', '๋ฒ ์ด๊ธ€', '๊ณฑ์ฐฝ', '์Šคํ…Œ์ดํฌ', '๊ณ ๊ธฐ',
38
+ '์‚ผ๊ฒน์‚ด', '์„ฑ์‹ฌ๋‹น', 'ํŽธ์˜์ ', '์ด์˜์ž', '๋ผ๋ฉด', '๊น€๋ฐฅ', '์น˜ํ‚จ', '๋ง›์ง‘', '์ง‘๋ฐฅ', '๋–ก๋ณถ์ด', '์Œ์‹', '๊น€์น˜',
39
+ '๊ด‘์–ด', '๋งŒ๋‘', '๋ƒ‰๋ฉด', '์ฒ ํŒ', '๋ผ์ง€', '์š”๋ฆฌ', '๊ฐ„์‹', 'ํšŒ์‹', '์ˆ ์ž๋ฆฌ', '๋ ˆ์‹œํ”ผ', '๊น€์น˜์ฐŒ๊ฐœ'],
40
+ '์—ฐ์˜ˆ/์œ ๋ช…์ธ': ['์ตœํ™”์ •', '์ดํ•ด๋ฆฌ', '๊ฐœ๊ทธ๋งจ', '๊ฐ•๋ฏผ๊ฒฝ', '๋‹ค๋น„์น˜', '์ด์ง€ํ˜œ', '์—ฌ์ž', '์•„์ด๋Œ', '๋‹ค๋‚˜์นด', '์ œ๋‹ˆ',
41
+ '์œ ์žฌ์„', 'ํ•‘๊ณ„๊ณ ', '์กฐ์„ธํ˜ธ', '์žฅ์˜๋ž€', '๊น€๊ตฌ๋ผ', '๊น€์˜์ฒ ', '์—ฐ์˜ˆ์ธ', '๋ฐฐ์šฐ', '์Šคํƒ€', '์ถœ์—ฐ', '์„ญ์™ธ',
42
+ '๊ฐ€์ˆ˜', '๋…ธ๋ž˜', '์ฝ˜์„œํŠธ', '์ด์Šน์ฒ '],
43
+ '๊ต์œก/๊ณต๋ถ€': ['์ผ์ฐจ๋ฐฉ์ •์‹', '์ด์ฐจ๋ฐฉ์ •์‹', '๋‹ฎ์Œ', '์ธ์ˆ˜๋ถ„ํ•ด', '์ง€์ˆ˜', '๋งž์ถค๋ฒ•', 'ํ•œ๊ตญ์‚ฌ', '๊ณผํ•™', '๊ณผ์™ธ', '์ˆ˜ํ•™',
44
+ '์ˆ˜์—…', '๊ณต๋ถ€', '์—ญ์‚ฌ', '๊ณต๋ถ€์™•', '์ˆ˜๋Šฅ', 'ํ€ด์ฆˆ', '์Šคํ„ฐ๋””', '์„ ์ƒ๋‹˜', '์‹œํ—˜', '์ง€์‹', '๋ฌธ์ œ',
45
+ '์ผ์ฐจํ•จ์ˆ˜', '์ด์ฐจํ•จ์ˆ˜', '๋ฐฉ์ •์‹', '๊ฒ€์ •๊ณ ์‹œ', '์˜์–ด', '๊ตญ์–ด', 'ํ•œ๊ตญ์–ด', '์„œ์šธ๋Œ€'],
46
+ '์—ฌํ–‰/์žฅ์†Œ': ['๋‘๋ฐ”์ด', 'ํœด๊ฐ€', '์ „๊ตญ', '์—ฌํ–‰', 'ํˆฌ์–ด', '์„ธ๊ณ„', '์ง€ํ•˜์ฒ ', 'ํ•œ๊ฐ•', '์นดํŽ˜', '์ฝ”์Šค', 'ํ•˜์™€์ด',
47
+ '๋„์ฟ„', '๋ชฝ๊ณจ', '์ผ๋ณธ', '์˜ค์‚ฌ์นด', '์ œ์ฃผ', '์ „์ฃผ', '์ œ์ฃผ๋„', '์„œ์šธ', '๋ฏผ๋ฐ•', '๋ฏธ๊ตญ', '๋Œ€๋งŒ',
48
+ 'ํŒŒ๋ฆฌ', '์ŠคํŽ˜์ธ', '์šธ๋ฆ‰๋„', 'ํ™์ฝฉ'],
49
+ '์ผ์ƒ/๊ฐ€์กฑ': ['๊ฐ€์กฑ', '์—„๋งˆ', '์•„๋น ', '๋‚จํŽธ', '์ž์‹', '๋ชจ๋…€', 'ํ˜ผ์ž', 'ํ•˜๋ฃจ', '์ผ์ƒ', '์‚ฌ๋žŒ', '์•„์ด', '๊ณต์œ ',
50
+ 'ํ˜„์žฅ', '๋ถ€๋ถ€', '๊ฐ€์žฅ', '์–ด๋จธ๋‹ˆ', '์กฐ์นด', '๊ฐ€์„', '์•„๋“ค', '๊ฒฐํ˜ผ์‹'],
51
+ '์ฝ˜ํ…์ธ /์œ ํŠœ๋ธŒ': ['์˜ˆ๋Šฅ', '์‹œ์ฆŒ', '๋ฆฌ๋ทฐ', '๋ผ์ด๋ธŒ', '๋ฐฉ์†ก', '์˜์ƒ', '์ฑ„๋„', '๊ฒŒ์ž„', '์œ ํŠœ๋ธŒ', '์ƒ๋ฐฉ์†ก',
52
+ '์ดฌ์˜', '์ฝ˜ํ…์ธ ', '๋Œ“๊ธ€', '์‡ผํ•‘'],
53
+ '์ •์น˜': ['๋Œ€์„ ', '๊ณต์•ฝ', '์•ˆ์ฒ ์ˆ˜', '๊ตญํšŒ', '์ •์น˜', '๋Œ€ํ†ต๋ น', '์„ ๊ฑฐ', '์ •๋‹น', '์˜์›'],
54
+ '๊ฒฝ์ œ': ['์ฃผ์‹', '๋น„ํŠธ์ฝ”์ธ', '์ฝ”์ธ', '์„ ๋ฌผ', '๋ถ€์ž', 'ํˆฌ์ž', '๊ฒฝ์ œ', '๊ธˆ์œต', '๊ด‘๊ณ ', '๋Œ€์ถœ', '์€ํ–‰', '์‹œ์žฅ'],
55
+ '๊ฑด๊ฐ•/์šด๋™': ['์šด๋™', '๊ฑด๊ฐ•', '๋‹ค์ด์–ดํŠธ', 'ํ—ฌ์Šค', '์ŠคํŠธ๋ ˆ์นญ', '์š”๊ฐ€', '์ฒด๋ ฅ', 'ํ”ผํŠธ๋‹ˆ์Šค', '๋‹ฌ๋ฆฌ๊ธฐ', '๊ทผ๋ ฅ', '์‹๋‹จ'],
56
+ '์ธ๊ฐ„๊ด€๊ณ„/๊ณ ๋ฏผ': ['์—ฐ์• ', '๊ณ ๋ฐฑ', '์†Œ๊ฐœํŒ…', '๋ฐ์ดํŠธ', '์†”๋กœ', '๊ณ ๋ฏผ']
57
+ }
58
+
59
+ # ์ œ๋ชฉ ํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜ ๋ถ„๋ฅ˜ ํ•จ์ˆ˜
60
+ def classify_by_keywords(title, keyword_dict):
61
+ for category, keywords in keyword_dict.items():
62
+ for keyword in keywords:
63
+ if keyword in title:
64
+ return category
65
+ return None
66
+
67
+ # ์œ ํŠœ๋ธŒ ์นดํ…Œ๊ณ ๋ฆฌ + ํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์šฉ์ž ์นดํ…Œ๊ณ ๋ฆฌ ๋ถ„๋ฅ˜
68
+ def map_category(category_id, title, api_key):
69
+ # ์œ ํŠœ๋ธŒ ์นดํ…Œ๊ณ ๋ฆฌ ์ด๋ฆ„ ๊ฐ€์ ธ์˜ค๊ธฐ
70
+ url = f'https://www.googleapis.com/youtube/v3/videoCategories?part=snippet&id={category_id}&regionCode=KR&key={api_key}'
71
+ try:
72
+ res = requests.get(url).json()
73
+ yt_category = res['items'][0]['snippet']['title']
74
+ except:
75
+ yt_category = "๊ธฐํƒ€"
76
+
77
+ # ์œ ํŠœ๋ธŒ ์นดํ…Œ๊ณ ๋ฆฌ๋ช… โ†’ ์‚ฌ์šฉ์ž ์นดํ…Œ๊ณ ๋ฆฌ ๋งคํ•‘
78
+ category_map = {
79
+ "์˜ํ™”/์• ๋‹ˆ๋ฉ”์ด์…˜": "์ฝ˜ํ…์ธ /์œ ํŠœ๋ธŒ",
80
+ "์Œ์•…": "์—ฐ์˜ˆ/์œ ๋ช…์ธ",
81
+ "์—”ํ„ฐํ…Œ์ธ๋จผํŠธ": "์ฝ˜ํ…์ธ /์œ ํŠœ๋ธŒ",
82
+ "์ฝ”๋ฏธ๋””": "์ฝ˜ํ…์ธ /์œ ํŠœ๋ธŒ",
83
+ "์ธ๋ฌผ/๋ธ”๋กœ๊ทธ": "์—ฐ์˜ˆ/์œ ๋ช…์ธ",
84
+ "๊ฒŒ์ž„": "์ฝ˜ํ…์ธ /์œ ํŠœ๋ธŒ",
85
+ "๋…ธํ•˜์šฐ/์Šคํƒ€์ผ": "์ผ์ƒ/๊ฐ€์กฑ",
86
+ "๋‰ด์Šค/์ •์น˜": "์ •์น˜",
87
+ "๊ต์œก": "๊ต์œก/๊ณต๋ถ€",
88
+ "๊ณผํ•™/๊ธฐ์ˆ ": "๊ต์œก/๊ณต๋ถ€",
89
+ "์Šคํฌ์ธ ": "๊ฑด๊ฐ•/์šด๋™",
90
+ "์ž๋™์ฐจ": "๊ธฐํƒ€",
91
+ "๋™๋ฌผ": "๊ธฐํƒ€",
92
+ "์—ฌํ–‰": "์—ฌํ–‰/์žฅ์†Œ"
93
+ }
94
+ mapped_category = category_map.get(yt_category, None)
95
+
96
+ # ํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜ ๋ณด์™„ ๋ถ„๋ฅ˜
97
+ keyword_category = classify_by_keywords(title, category_dict)
98
+
99
+ # ์ตœ์ข… ์šฐ์„ ์ˆœ์œ„ ์ ์šฉ
100
+ return keyword_category or mapped_category or "๊ธฐํƒ€"
101
+
102
+ def hue_to_color_group(hue_value):
103
+ if 0 <= hue_value < 15 or hue_value >= 345:
104
+ return "๋นจ๊ฐ• ๊ณ„์—ด"
105
+ elif 15 <= hue_value < 45:
106
+ return "์ฃผํ™ฉ/๋…ธ๋ž‘ ๊ณ„์—ด"
107
+ elif 45 <= hue_value < 75:
108
+ return "์—ฐ๋‘/์ดˆ๋ก ๊ณ„์—ด"
109
+ elif 75 <= hue_value < 165:
110
+ return "์ดˆ๋ก/ํ•˜๋Š˜ ๊ณ„์—ด"
111
+ elif 165 <= hue_value < 255:
112
+ return "ํŒŒ๋ž‘/๋‚จ์ƒ‰ ๊ณ„์—ด"
113
+ elif 255 <= hue_value < 285:
114
+ return "๋ณด๋ผ ๊ณ„์—ด"
115
+ elif 285 <= hue_value < 345:
116
+ return "๋ถ„ํ™ ๊ณ„์—ด"
117
+ else:
118
+ return "๊ธฐํƒ€"
119
+
120
+ def analyze_thumbnail(thumbnail_url):
121
+ response = requests.get(thumbnail_url)
122
+ img = Image.open(BytesIO(response.content)).convert('RGB')
123
+ img_np = np.array(img)
124
+ hsv = cv2.cvtColor(img_np, cv2.COLOR_RGB2HSV)
125
+ hue_avg = int(np.mean(hsv[:, :, 0]) * 2)
126
+
127
+ # ์–ผ๊ตด ์ˆ˜ ๊ฒ€์ถœ
128
+ mp_face = mp.solutions.face_detection
129
+ with mp_face.FaceDetection(model_selection=1, min_detection_confidence=0.3) as fd:
130
+ results = fd.process(cv2.cvtColor(img_np, cv2.COLOR_RGB2BGR))
131
+ face_count = len(results.detections) if results.detections else 0
132
+
133
+ return hue_to_color_group(hue_avg), face_count, hue_avg
134
+
135
+ def predict_views(video_id, api_key):
136
+ url = f'https://www.googleapis.com/youtube/v3/videos?part=snippet,statistics&id={video_id}&key={api_key}'
137
+ res = requests.get(url).json()
138
+ item = res['items'][0]
139
+
140
+ title = item['snippet']['title']
141
+ published_at = item['snippet']['publishedAt']
142
+ category_id = item['snippet'].get('categoryId', '')
143
+ thumbnail_url = item['snippet']['thumbnails']['high']['url']
144
+ views = int(item['statistics'].get('viewCount', 0))
145
+
146
+ # ๊ฒŒ์‹œ์ผ ์ •๋ณด
147
+ dt = pd.to_datetime(published_at)
148
+ hour = dt.hour
149
+ weekday = dt.dayofweek
150
+
151
+ # ์ž๋ง‰ ์ˆ˜
152
+ def count_manual_subtitles(video_id):
153
+ ppl = YouTubeTranscriptApi.list_transcripts(video_id)
154
+ manual = [t for t in ppl if not t.is_generated]
155
+ return len(manual)
156
+
157
+ caption_count = count_manual_subtitles(video_id)
158
+
159
+ # ์ธ๋„ค์ผ ๋ถ„์„
160
+ hue_group, face_count, hue_value = analyze_thumbnail(thumbnail_url)
161
+
162
+ # ๊ฐ์„ฑ ์ ์ˆ˜
163
+ senti = sentiment_score(title)
164
+
165
+ # ์นดํ…Œ๊ณ ๋ฆฌ ์ด๋ฆ„ ๋งคํ•‘
166
+ user_category = map_category(category_id, title, api_key)
167
+
168
+ # Label Encoding
169
+ if user_category not in le_cat.classes_:
170
+ user_category = '๊ธฐํƒ€'
171
+ cat_encoded = le_cat.transform([user_category])[0]
172
+
173
+ # ์˜ˆ์ธก
174
+ X_input = pd.DataFrame([{
175
+ '์‹œ๊ฐ„๋Œ€': hour,
176
+ '์š”์ผ': weekday,
177
+ '์ž๋ง‰์ˆ˜': caption_count,
178
+ '์นดํ…Œ๊ณ ๋ฆฌ': cat_encoded,
179
+ 'Hue': hue_value,
180
+ '์ธ๋„ค์ผ ์–ผ๊ตด ์ˆ˜': face_count,
181
+ '๊ฐ์„ฑ์ ์ˆ˜': senti
182
+ }])
183
+
184
+ pred_log = model.predict(X_input[feature_cols])[0]
185
+ predicted_views = int(np.expm1(pred_log))
186
+
187
+ return {
188
+ '์ œ๋ชฉ': title,
189
+ '์˜ˆ์ธก ์กฐํšŒ์ˆ˜': predicted_views,
190
+ '์‹ค์ œ ์กฐํšŒ์ˆ˜': views,
191
+ '์นดํ…Œ๊ณ ๋ฆฌ': user_category,
192
+ '์‹œ๊ฐ„๋Œ€': hour,
193
+ '์š”์ผ': weekday,
194
+ '์ž๋ง‰์ˆ˜': caption_count,
195
+ '์ธ๋„ค์ผ ์–ผ๊ตด ์ˆ˜': face_count,
196
+ '๊ฐ์„ฑ์ ์ˆ˜': senti,
197
+ 'Hue ๊ทธ๋ฃน': hue_group,
198
+ 'Hue ๊ฐ’': hue_value,
199
+ '์ธ๋„ค์ผ URL': thumbnail_url
200
+ }
201
+
202
+ #1. ์ถ”์ธก ํ•จ์ˆ˜
203
+ def extract_features_from_video_id(video_id, api_key):
204
+ info = predict_views(video_id, api_key)
205
+ return pd.DataFrame([{
206
+ '์‹œ๊ฐ„๋Œ€': info['์‹œ๊ฐ„๋Œ€'],
207
+ '์š”์ผ': info['์š”์ผ'],
208
+ '์ž๋ง‰์ˆ˜': info['์ž๋ง‰์ˆ˜'],
209
+ '์นดํ…Œ๊ณ ๋ฆฌ': le_cat.transform([info['์นดํ…Œ๊ณ ๋ฆฌ']])[0],
210
+ 'Hue': info['Hue ๊ฐ’'],
211
+ '์ธ๋„ค์ผ ์–ผ๊ตด ์ˆ˜': info['์ธ๋„ค์ผ ์–ผ๊ตด ์ˆ˜'],
212
+ '๊ฐ์„ฑ์ ์ˆ˜': info['๊ฐ์„ฑ์ ์ˆ˜']
213
+ }])
214
+
215
+ # 2. ์˜ˆ์ธก ํ•จ์ˆ˜
216
+ def predict_view_count(model, features):
217
+ pred_log = model.predict(features[feature_cols])[0]
218
+ return int(np.expm1(pred_log))
219
+
220
+ # 3. ์‹œ๊ฐํ™” ํ•จ์ˆ˜
221
+ def visualize_result(video_id, features, predicted_view_count, info):
222
+ ์š”์ผ_ํ…์ŠคํŠธ = ['์›”', 'ํ™”', '์ˆ˜', '๋ชฉ', '๊ธˆ', 'ํ† ', '์ผ'][features['์š”์ผ'].values[0]]
223
+
224
+ html = f"""
225
+ <div style="background-color: #111; color: white; padding: 20px; border-radius: 10px; max-width: 600px; font-family: Arial, sans-serif;">
226
+ <h2>๐ŸŽฏ ์˜ˆ์ธก ์กฐํšŒ์ˆ˜: {predicted_view_count:,}ํšŒ</h2>
227
+ <h3>๐Ÿ“Œ ์˜์ƒ ์ œ๋ชฉ: {info['์ œ๋ชฉ']}</h3>
228
+ <img src="{info['์ธ๋„ค์ผ URL']}" alt="์ธ๋„ค์ผ ์ด๋ฏธ์ง€" style="width: 100%; border-radius: 10px; margin-bottom: 20px;"/>
229
+ <ul style="list-style-type: none; padding-left: 0;">
230
+ <li>๐Ÿ“ฝ๏ธ <strong>์˜์ƒ ID:</strong> {video_id}</li>
231
+ <li>๐Ÿ‘๏ธ <strong>์‹ค์ œ ์กฐํšŒ์ˆ˜:</strong> {info['๏ฟฝ๏ฟฝ๏ฟฝ์ œ ์กฐํšŒ์ˆ˜']:,}ํšŒ</li>
232
+ <li>โฐ <strong>์‹œ๊ฐ„๋Œ€:</strong> {features['์‹œ๊ฐ„๋Œ€'].values[0]}์‹œ</li>
233
+ <li>๐Ÿ“… <strong>์š”์ผ:</strong> {์š”์ผ_ํ…์ŠคํŠธ}</li>
234
+ <li>๐Ÿ’ฌ <strong>์ž๋ง‰ ์ˆ˜:</strong> {features['์ž๋ง‰์ˆ˜'].values[0]}</li>
235
+ <li>๐ŸŽจ <strong>์ƒ‰์ƒ ๊ณ„์—ด:</strong> {info['Hue ๊ทธ๋ฃน']}</li>
236
+ <li>๐Ÿ˜ƒ <strong>์ธ๋„ค์ผ ์–ผ๊ตด ์ˆ˜:</strong> {features['์ธ๋„ค์ผ ์–ผ๊ตด ์ˆ˜'].values[0]}</li>
237
+ <li>๐Ÿง  <strong>๊ฐ์„ฑ ์ ์ˆ˜:</strong> {features['๊ฐ์„ฑ์ ์ˆ˜'].values[0]:.2f}</li>
238
+ </ul>
239
+ </div>
240
+ """
241
+ return html
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ pandas
3
+ numpy
4
+ requests
5
+ opencv-python-headless
6
+ mediapipe
7
+ torch
8
+ Pillow
9
+ joblib
10
+ transformers
11
+ youtube-transcript-api
view_predictor.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8e6382db2936fcc04e3594c5731d64eddf3e7b4efdbf78490f877d5641a4b548
3
+ size 17581281