nate wright
commited on
Commit
•
b2e30fd
1
Parent(s):
83f7b23
Upload 12 files
Browse filesModel and python training files
- model/config.json +62 -0
- model/generation_config.json +7 -0
- model/pytorch_model.bin +3 -0
- model/special_tokens_map.json +107 -0
- model/spiece.model +3 -0
- model/tokenizer.json +0 -0
- model/tokenizer_config.json +112 -0
- model_training.py +76 -0
- test.csv +0 -0
- test_model.py +19 -0
- transcript_downloader.py +101 -0
- urls.csv +1 -0
model/config.json
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"_name_or_path": "google/flan-t5-small",
|
3 |
+
"architectures": [
|
4 |
+
"T5ForConditionalGeneration"
|
5 |
+
],
|
6 |
+
"classifier_dropout": 0.0,
|
7 |
+
"d_ff": 1024,
|
8 |
+
"d_kv": 64,
|
9 |
+
"d_model": 512,
|
10 |
+
"decoder_start_token_id": 0,
|
11 |
+
"dense_act_fn": "gelu_new",
|
12 |
+
"dropout_rate": 0.1,
|
13 |
+
"eos_token_id": 1,
|
14 |
+
"feed_forward_proj": "gated-gelu",
|
15 |
+
"initializer_factor": 1.0,
|
16 |
+
"is_encoder_decoder": true,
|
17 |
+
"is_gated_act": true,
|
18 |
+
"layer_norm_epsilon": 1e-06,
|
19 |
+
"model_type": "t5",
|
20 |
+
"n_positions": 512,
|
21 |
+
"num_decoder_layers": 8,
|
22 |
+
"num_heads": 6,
|
23 |
+
"num_layers": 8,
|
24 |
+
"output_past": true,
|
25 |
+
"pad_token_id": 0,
|
26 |
+
"relative_attention_max_distance": 128,
|
27 |
+
"relative_attention_num_buckets": 32,
|
28 |
+
"task_specific_params": {
|
29 |
+
"summarization": {
|
30 |
+
"early_stopping": true,
|
31 |
+
"length_penalty": 2.0,
|
32 |
+
"max_length": 200,
|
33 |
+
"min_length": 30,
|
34 |
+
"no_repeat_ngram_size": 3,
|
35 |
+
"num_beams": 4,
|
36 |
+
"prefix": "summarize: "
|
37 |
+
},
|
38 |
+
"translation_en_to_de": {
|
39 |
+
"early_stopping": true,
|
40 |
+
"max_length": 300,
|
41 |
+
"num_beams": 4,
|
42 |
+
"prefix": "translate English to German: "
|
43 |
+
},
|
44 |
+
"translation_en_to_fr": {
|
45 |
+
"early_stopping": true,
|
46 |
+
"max_length": 300,
|
47 |
+
"num_beams": 4,
|
48 |
+
"prefix": "translate English to French: "
|
49 |
+
},
|
50 |
+
"translation_en_to_ro": {
|
51 |
+
"early_stopping": true,
|
52 |
+
"max_length": 300,
|
53 |
+
"num_beams": 4,
|
54 |
+
"prefix": "translate English to Romanian: "
|
55 |
+
}
|
56 |
+
},
|
57 |
+
"tie_word_embeddings": false,
|
58 |
+
"torch_dtype": "float32",
|
59 |
+
"transformers_version": "4.33.2",
|
60 |
+
"use_cache": true,
|
61 |
+
"vocab_size": 32128
|
62 |
+
}
|
model/generation_config.json
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"_from_model_config": true,
|
3 |
+
"decoder_start_token_id": 0,
|
4 |
+
"eos_token_id": 1,
|
5 |
+
"pad_token_id": 0,
|
6 |
+
"transformers_version": "4.33.2"
|
7 |
+
}
|
model/pytorch_model.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:1e5838dc0a49ce85ea877140feae20f5fd1b9d1bbb460f535c3f9ffae494ae03
|
3 |
+
size 307907461
|
model/special_tokens_map.json
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"additional_special_tokens": [
|
3 |
+
"<extra_id_0>",
|
4 |
+
"<extra_id_1>",
|
5 |
+
"<extra_id_2>",
|
6 |
+
"<extra_id_3>",
|
7 |
+
"<extra_id_4>",
|
8 |
+
"<extra_id_5>",
|
9 |
+
"<extra_id_6>",
|
10 |
+
"<extra_id_7>",
|
11 |
+
"<extra_id_8>",
|
12 |
+
"<extra_id_9>",
|
13 |
+
"<extra_id_10>",
|
14 |
+
"<extra_id_11>",
|
15 |
+
"<extra_id_12>",
|
16 |
+
"<extra_id_13>",
|
17 |
+
"<extra_id_14>",
|
18 |
+
"<extra_id_15>",
|
19 |
+
"<extra_id_16>",
|
20 |
+
"<extra_id_17>",
|
21 |
+
"<extra_id_18>",
|
22 |
+
"<extra_id_19>",
|
23 |
+
"<extra_id_20>",
|
24 |
+
"<extra_id_21>",
|
25 |
+
"<extra_id_22>",
|
26 |
+
"<extra_id_23>",
|
27 |
+
"<extra_id_24>",
|
28 |
+
"<extra_id_25>",
|
29 |
+
"<extra_id_26>",
|
30 |
+
"<extra_id_27>",
|
31 |
+
"<extra_id_28>",
|
32 |
+
"<extra_id_29>",
|
33 |
+
"<extra_id_30>",
|
34 |
+
"<extra_id_31>",
|
35 |
+
"<extra_id_32>",
|
36 |
+
"<extra_id_33>",
|
37 |
+
"<extra_id_34>",
|
38 |
+
"<extra_id_35>",
|
39 |
+
"<extra_id_36>",
|
40 |
+
"<extra_id_37>",
|
41 |
+
"<extra_id_38>",
|
42 |
+
"<extra_id_39>",
|
43 |
+
"<extra_id_40>",
|
44 |
+
"<extra_id_41>",
|
45 |
+
"<extra_id_42>",
|
46 |
+
"<extra_id_43>",
|
47 |
+
"<extra_id_44>",
|
48 |
+
"<extra_id_45>",
|
49 |
+
"<extra_id_46>",
|
50 |
+
"<extra_id_47>",
|
51 |
+
"<extra_id_48>",
|
52 |
+
"<extra_id_49>",
|
53 |
+
"<extra_id_50>",
|
54 |
+
"<extra_id_51>",
|
55 |
+
"<extra_id_52>",
|
56 |
+
"<extra_id_53>",
|
57 |
+
"<extra_id_54>",
|
58 |
+
"<extra_id_55>",
|
59 |
+
"<extra_id_56>",
|
60 |
+
"<extra_id_57>",
|
61 |
+
"<extra_id_58>",
|
62 |
+
"<extra_id_59>",
|
63 |
+
"<extra_id_60>",
|
64 |
+
"<extra_id_61>",
|
65 |
+
"<extra_id_62>",
|
66 |
+
"<extra_id_63>",
|
67 |
+
"<extra_id_64>",
|
68 |
+
"<extra_id_65>",
|
69 |
+
"<extra_id_66>",
|
70 |
+
"<extra_id_67>",
|
71 |
+
"<extra_id_68>",
|
72 |
+
"<extra_id_69>",
|
73 |
+
"<extra_id_70>",
|
74 |
+
"<extra_id_71>",
|
75 |
+
"<extra_id_72>",
|
76 |
+
"<extra_id_73>",
|
77 |
+
"<extra_id_74>",
|
78 |
+
"<extra_id_75>",
|
79 |
+
"<extra_id_76>",
|
80 |
+
"<extra_id_77>",
|
81 |
+
"<extra_id_78>",
|
82 |
+
"<extra_id_79>",
|
83 |
+
"<extra_id_80>",
|
84 |
+
"<extra_id_81>",
|
85 |
+
"<extra_id_82>",
|
86 |
+
"<extra_id_83>",
|
87 |
+
"<extra_id_84>",
|
88 |
+
"<extra_id_85>",
|
89 |
+
"<extra_id_86>",
|
90 |
+
"<extra_id_87>",
|
91 |
+
"<extra_id_88>",
|
92 |
+
"<extra_id_89>",
|
93 |
+
"<extra_id_90>",
|
94 |
+
"<extra_id_91>",
|
95 |
+
"<extra_id_92>",
|
96 |
+
"<extra_id_93>",
|
97 |
+
"<extra_id_94>",
|
98 |
+
"<extra_id_95>",
|
99 |
+
"<extra_id_96>",
|
100 |
+
"<extra_id_97>",
|
101 |
+
"<extra_id_98>",
|
102 |
+
"<extra_id_99>"
|
103 |
+
],
|
104 |
+
"eos_token": "</s>",
|
105 |
+
"pad_token": "</s>",
|
106 |
+
"unk_token": "<unk>"
|
107 |
+
}
|
model/spiece.model
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:d60acb128cf7b7f2536e8f38a5b18a05535c9e14c7a355904270e15b0945ea86
|
3 |
+
size 791656
|
model/tokenizer.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
model/tokenizer_config.json
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"additional_special_tokens": [
|
3 |
+
"<extra_id_0>",
|
4 |
+
"<extra_id_1>",
|
5 |
+
"<extra_id_2>",
|
6 |
+
"<extra_id_3>",
|
7 |
+
"<extra_id_4>",
|
8 |
+
"<extra_id_5>",
|
9 |
+
"<extra_id_6>",
|
10 |
+
"<extra_id_7>",
|
11 |
+
"<extra_id_8>",
|
12 |
+
"<extra_id_9>",
|
13 |
+
"<extra_id_10>",
|
14 |
+
"<extra_id_11>",
|
15 |
+
"<extra_id_12>",
|
16 |
+
"<extra_id_13>",
|
17 |
+
"<extra_id_14>",
|
18 |
+
"<extra_id_15>",
|
19 |
+
"<extra_id_16>",
|
20 |
+
"<extra_id_17>",
|
21 |
+
"<extra_id_18>",
|
22 |
+
"<extra_id_19>",
|
23 |
+
"<extra_id_20>",
|
24 |
+
"<extra_id_21>",
|
25 |
+
"<extra_id_22>",
|
26 |
+
"<extra_id_23>",
|
27 |
+
"<extra_id_24>",
|
28 |
+
"<extra_id_25>",
|
29 |
+
"<extra_id_26>",
|
30 |
+
"<extra_id_27>",
|
31 |
+
"<extra_id_28>",
|
32 |
+
"<extra_id_29>",
|
33 |
+
"<extra_id_30>",
|
34 |
+
"<extra_id_31>",
|
35 |
+
"<extra_id_32>",
|
36 |
+
"<extra_id_33>",
|
37 |
+
"<extra_id_34>",
|
38 |
+
"<extra_id_35>",
|
39 |
+
"<extra_id_36>",
|
40 |
+
"<extra_id_37>",
|
41 |
+
"<extra_id_38>",
|
42 |
+
"<extra_id_39>",
|
43 |
+
"<extra_id_40>",
|
44 |
+
"<extra_id_41>",
|
45 |
+
"<extra_id_42>",
|
46 |
+
"<extra_id_43>",
|
47 |
+
"<extra_id_44>",
|
48 |
+
"<extra_id_45>",
|
49 |
+
"<extra_id_46>",
|
50 |
+
"<extra_id_47>",
|
51 |
+
"<extra_id_48>",
|
52 |
+
"<extra_id_49>",
|
53 |
+
"<extra_id_50>",
|
54 |
+
"<extra_id_51>",
|
55 |
+
"<extra_id_52>",
|
56 |
+
"<extra_id_53>",
|
57 |
+
"<extra_id_54>",
|
58 |
+
"<extra_id_55>",
|
59 |
+
"<extra_id_56>",
|
60 |
+
"<extra_id_57>",
|
61 |
+
"<extra_id_58>",
|
62 |
+
"<extra_id_59>",
|
63 |
+
"<extra_id_60>",
|
64 |
+
"<extra_id_61>",
|
65 |
+
"<extra_id_62>",
|
66 |
+
"<extra_id_63>",
|
67 |
+
"<extra_id_64>",
|
68 |
+
"<extra_id_65>",
|
69 |
+
"<extra_id_66>",
|
70 |
+
"<extra_id_67>",
|
71 |
+
"<extra_id_68>",
|
72 |
+
"<extra_id_69>",
|
73 |
+
"<extra_id_70>",
|
74 |
+
"<extra_id_71>",
|
75 |
+
"<extra_id_72>",
|
76 |
+
"<extra_id_73>",
|
77 |
+
"<extra_id_74>",
|
78 |
+
"<extra_id_75>",
|
79 |
+
"<extra_id_76>",
|
80 |
+
"<extra_id_77>",
|
81 |
+
"<extra_id_78>",
|
82 |
+
"<extra_id_79>",
|
83 |
+
"<extra_id_80>",
|
84 |
+
"<extra_id_81>",
|
85 |
+
"<extra_id_82>",
|
86 |
+
"<extra_id_83>",
|
87 |
+
"<extra_id_84>",
|
88 |
+
"<extra_id_85>",
|
89 |
+
"<extra_id_86>",
|
90 |
+
"<extra_id_87>",
|
91 |
+
"<extra_id_88>",
|
92 |
+
"<extra_id_89>",
|
93 |
+
"<extra_id_90>",
|
94 |
+
"<extra_id_91>",
|
95 |
+
"<extra_id_92>",
|
96 |
+
"<extra_id_93>",
|
97 |
+
"<extra_id_94>",
|
98 |
+
"<extra_id_95>",
|
99 |
+
"<extra_id_96>",
|
100 |
+
"<extra_id_97>",
|
101 |
+
"<extra_id_98>",
|
102 |
+
"<extra_id_99>"
|
103 |
+
],
|
104 |
+
"clean_up_tokenization_spaces": true,
|
105 |
+
"eos_token": "</s>",
|
106 |
+
"extra_ids": 100,
|
107 |
+
"model_max_length": 512,
|
108 |
+
"pad_token": "<pad>",
|
109 |
+
"sp_model_kwargs": {},
|
110 |
+
"tokenizer_class": "T5Tokenizer",
|
111 |
+
"unk_token": "<unk>"
|
112 |
+
}
|
model_training.py
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from transformers import DataCollatorForLanguageModeling, Trainer, TrainingArguments, AutoTokenizer, AutoModelForSeq2SeqLM
|
3 |
+
from datasets import load_dataset, Dataset
|
4 |
+
|
5 |
+
os.environ['TOKENIZERS_PARALLELISM'] = 'true'
|
6 |
+
|
7 |
+
|
8 |
+
def load_transcripts(directory):
|
9 |
+
transcript_texts = []
|
10 |
+
for filename in os.listdir(directory):
|
11 |
+
if filename.endswith('.txt'):
|
12 |
+
file_path = os.path.join(directory, filename)
|
13 |
+
with open(file_path, 'r', encoding='utf-8') as file:
|
14 |
+
transcript_texts.append(file.read())
|
15 |
+
return transcript_texts
|
16 |
+
|
17 |
+
|
18 |
+
def main():
|
19 |
+
tokenizer = AutoTokenizer.from_pretrained("google/flan-t5-small")
|
20 |
+
model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-small")
|
21 |
+
|
22 |
+
tokenizer.pad_token = tokenizer.eos_token # Set a padding token
|
23 |
+
|
24 |
+
datasets = load_dataset(
|
25 |
+
'csv', data_files={'test': 'test.csv'})
|
26 |
+
|
27 |
+
test_dataset = datasets['test'].map(
|
28 |
+
lambda examples: tokenizer(
|
29 |
+
examples['transcript'], truncation=True, padding='max_length', return_attention_mask=False),
|
30 |
+
batched=True
|
31 |
+
)
|
32 |
+
|
33 |
+
transcripts = load_transcripts('transcripts')
|
34 |
+
train_encodings = tokenizer(transcripts, truncation=True,
|
35 |
+
padding='max_length', max_length=tokenizer.model_max_length)
|
36 |
+
train_dataset = Dataset.from_dict(
|
37 |
+
{"input_ids": train_encodings["input_ids"], "attention_mask": train_encodings["attention_mask"]})
|
38 |
+
|
39 |
+
data_collator = DataCollatorForLanguageModeling(
|
40 |
+
tokenizer=tokenizer, mlm=False)
|
41 |
+
|
42 |
+
training_args = TrainingArguments(
|
43 |
+
output_dir="./model",
|
44 |
+
overwrite_output_dir=True,
|
45 |
+
num_train_epochs=3,
|
46 |
+
per_device_train_batch_size=4,
|
47 |
+
gradient_accumulation_steps=4,
|
48 |
+
save_steps=2_000,
|
49 |
+
save_total_limit=2,
|
50 |
+
logging_dir='./logs',
|
51 |
+
learning_rate=5e-5,
|
52 |
+
weight_decay=0.01,
|
53 |
+
evaluation_strategy="steps",
|
54 |
+
eval_steps=500,
|
55 |
+
warmup_steps=300
|
56 |
+
)
|
57 |
+
|
58 |
+
trainer = Trainer(
|
59 |
+
model=model,
|
60 |
+
args=training_args,
|
61 |
+
data_collator=data_collator,
|
62 |
+
train_dataset=train_dataset,
|
63 |
+
eval_dataset=test_dataset,
|
64 |
+
)
|
65 |
+
|
66 |
+
# Training
|
67 |
+
trainer.train()
|
68 |
+
trainer.evaluate()
|
69 |
+
|
70 |
+
# Saving the trained model
|
71 |
+
model.save_pretrained("./model")
|
72 |
+
tokenizer.save_pretrained("./model")
|
73 |
+
|
74 |
+
|
75 |
+
if __name__ == "__main__":
|
76 |
+
main()
|
test.csv
ADDED
The diff for this file is too large to render.
See raw diff
|
|
test_model.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
|
2 |
+
|
3 |
+
# Load the trained model and tokenizer
|
4 |
+
model = AutoModelForSeq2SeqLM.from_pretrained("./model")
|
5 |
+
tokenizer = AutoTokenizer.from_pretrained("./model", model_max_length=512)
|
6 |
+
|
7 |
+
|
8 |
+
# Prepare the text you want to use as a prompt
|
9 |
+
text = "premise: woman are emotional creatures. outcome: why do woman get upset easily?"
|
10 |
+
|
11 |
+
|
12 |
+
# Encode the text and run it through the model
|
13 |
+
input_ids = tokenizer(text, return_tensors="pt").input_ids
|
14 |
+
outputs = model.generate(input_ids, max_length=500,
|
15 |
+
num_return_sequences=1)
|
16 |
+
|
17 |
+
# Decode and print the output text
|
18 |
+
decoded = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
19 |
+
print(decoded)
|
transcript_downloader.py
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import csv
|
2 |
+
import re
|
3 |
+
import os
|
4 |
+
import yt_dlp
|
5 |
+
import whisper
|
6 |
+
from tqdm import tqdm
|
7 |
+
import ssl
|
8 |
+
|
9 |
+
ssl._create_default_https_context = ssl._create_unverified_context
|
10 |
+
|
11 |
+
|
12 |
+
# Folder to save audio and transcripts
|
13 |
+
audio_folder = 'audio_files'
|
14 |
+
transcripts_folder = 'transcripts'
|
15 |
+
|
16 |
+
|
17 |
+
def sanitize_filename(filename):
|
18 |
+
"""
|
19 |
+
Removes invalid characters from filename and truncates it if it's too long.
|
20 |
+
"""
|
21 |
+
s = re.sub(r'[\\/*?:"<>|]', '', filename)
|
22 |
+
if len(s) > 200:
|
23 |
+
s = s[:200]
|
24 |
+
return s
|
25 |
+
|
26 |
+
|
27 |
+
def download_audio_with_yt_dlp(video_id):
|
28 |
+
ydl_opts = {
|
29 |
+
'format': 'bestaudio/best',
|
30 |
+
'postprocessors': [{
|
31 |
+
'key': 'FFmpegExtractAudio',
|
32 |
+
'preferredcodec': 'mp3'
|
33 |
+
}],
|
34 |
+
'outtmpl': f'{audio_folder}/{video_id}.%(ext)s'
|
35 |
+
}
|
36 |
+
|
37 |
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
38 |
+
ydl.download([f'https://www.youtube.com/watch?v={video_id}'])
|
39 |
+
|
40 |
+
|
41 |
+
def transcribe_audio_with_whisper(audio_file):
|
42 |
+
model = whisper.load_model("base")
|
43 |
+
result = model.transcribe(audio_file)
|
44 |
+
return result["text"]
|
45 |
+
|
46 |
+
|
47 |
+
def process_video(video_id):
|
48 |
+
audio_file = f"{audio_folder}/{video_id}.mp3"
|
49 |
+
|
50 |
+
# Download audio
|
51 |
+
download_audio_with_yt_dlp(video_id)
|
52 |
+
|
53 |
+
# Transcribe audio
|
54 |
+
transcript = transcribe_audio_with_whisper(audio_file)
|
55 |
+
|
56 |
+
# Save the transcript
|
57 |
+
with open(f"{transcripts_folder}/{video_id}.txt", 'w', encoding="utf-8") as outfile:
|
58 |
+
outfile.write(transcript)
|
59 |
+
|
60 |
+
|
61 |
+
def download_audio_from_playlist(playlist_url):
|
62 |
+
ydl_opts = {
|
63 |
+
'format': 'bestaudio/best',
|
64 |
+
'postprocessors': [{
|
65 |
+
'key': 'FFmpegExtractAudio',
|
66 |
+
'preferredcodec': 'mp3',
|
67 |
+
'preferredquality': '192',
|
68 |
+
}],
|
69 |
+
'outtmpl': f'{audio_folder}/%(id)s.%(ext)s',
|
70 |
+
'ignoreerrors': True, # Continue on download errors
|
71 |
+
'extract_flat': True, # Just get video IDs from the playlist
|
72 |
+
}
|
73 |
+
|
74 |
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
75 |
+
info_dict = ydl.extract_info(playlist_url, download=False)
|
76 |
+
for video in info_dict['entries']:
|
77 |
+
if video: # Video is not None or deleted
|
78 |
+
process_video(video['id'])
|
79 |
+
|
80 |
+
|
81 |
+
def download_transcripts_from_csv(file_path):
|
82 |
+
with open(file_path, 'r') as csvfile:
|
83 |
+
reader = csv.reader(csvfile)
|
84 |
+
for row in tqdm(reader):
|
85 |
+
url = row[0]
|
86 |
+
if "list=" in url:
|
87 |
+
# It's a playlist, process each video in the playlist
|
88 |
+
download_audio_from_playlist(url)
|
89 |
+
else:
|
90 |
+
# It's a single video
|
91 |
+
video_id = url.split('v=')[-1]
|
92 |
+
process_video(video_id)
|
93 |
+
|
94 |
+
|
95 |
+
if __name__ == "__main__":
|
96 |
+
# Ensure folders exist
|
97 |
+
os.makedirs(audio_folder, exist_ok=True)
|
98 |
+
os.makedirs(transcripts_folder, exist_ok=True)
|
99 |
+
|
100 |
+
csv_path = 'urls.csv'
|
101 |
+
download_transcripts_from_csv(csv_path)
|
urls.csv
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
https://www.youtube.com/playlist?list=PLB13i9vubrBfR0IfNO6ueZBPH_S7Zo0Po
|