mirror of
https://github.com/yihong0618/bilingual_book_maker.git
synced 2025-06-02 09:30:24 +00:00
parent
a0c999a2e6
commit
1720c95d44
@ -1,8 +1,10 @@
|
|||||||
from book_maker.loader.epub_loader import EPUBBookLoader
|
from book_maker.loader.epub_loader import EPUBBookLoader
|
||||||
from book_maker.loader.txt_loader import TXTBookLoader
|
from book_maker.loader.txt_loader import TXTBookLoader
|
||||||
|
from book_maker.loader.srt_loader import SRTBookLoader
|
||||||
|
|
||||||
BOOK_LOADER_DICT = {
|
BOOK_LOADER_DICT = {
|
||||||
"epub": EPUBBookLoader,
|
"epub": EPUBBookLoader,
|
||||||
"txt": TXTBookLoader
|
"txt": TXTBookLoader,
|
||||||
|
"srt": SRTBookLoader,
|
||||||
# TODO add more here
|
# TODO add more here
|
||||||
}
|
}
|
||||||
|
@ -1 +1,278 @@
|
|||||||
"""TODO"""
|
"""
|
||||||
|
inspired by: https://github.com/jesselau76/srt-gpt-translator, MIT License
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from book_maker.utils import prompt_config_to_kwargs
|
||||||
|
|
||||||
|
from .base_loader import BaseBookLoader
|
||||||
|
|
||||||
|
|
||||||
|
class SRTBookLoader(BaseBookLoader):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
srt_name,
|
||||||
|
model,
|
||||||
|
key,
|
||||||
|
resume,
|
||||||
|
language,
|
||||||
|
model_api_base=None,
|
||||||
|
is_test=False,
|
||||||
|
test_num=5,
|
||||||
|
prompt_config=None,
|
||||||
|
single_translate=False,
|
||||||
|
) -> None:
|
||||||
|
self.srt_name = srt_name
|
||||||
|
self.translate_model = model(
|
||||||
|
key,
|
||||||
|
language,
|
||||||
|
api_base=model_api_base,
|
||||||
|
**prompt_config_to_kwargs(
|
||||||
|
{
|
||||||
|
"system": "You are a srt subtitle file translator.",
|
||||||
|
"user": "Translate the following subtitle text into {language}, but keep the subtitle number and timeline and newlines unchanged: \n{text}",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.is_test = is_test
|
||||||
|
self.p_to_save = []
|
||||||
|
self.bilingual_result = []
|
||||||
|
self.bilingual_temp_result = []
|
||||||
|
self.test_num = test_num
|
||||||
|
self.accumulated_num = 1
|
||||||
|
self.blocks = []
|
||||||
|
|
||||||
|
self.resume = resume
|
||||||
|
self.bin_path = f"{Path(srt_name).parent}/.{Path(srt_name).stem}.temp.bin"
|
||||||
|
if self.resume:
|
||||||
|
self.load_state()
|
||||||
|
|
||||||
|
def _make_new_book(self, book):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _parse_srt(self, srt_text):
|
||||||
|
blocks = re.split("\n\s*\n", srt_text)
|
||||||
|
|
||||||
|
final_blocks = []
|
||||||
|
new_block = {}
|
||||||
|
for i in range(0, len(blocks)):
|
||||||
|
block = blocks[i]
|
||||||
|
if block.strip() == "":
|
||||||
|
continue
|
||||||
|
|
||||||
|
lines = block.strip().split("\n")
|
||||||
|
new_block["number"] = lines[0].strip()
|
||||||
|
timestamp = lines[1].strip()
|
||||||
|
new_block["time"] = timestamp
|
||||||
|
text = "\n".join(lines[2:]).strip()
|
||||||
|
new_block["text"] = text
|
||||||
|
final_blocks.append(new_block)
|
||||||
|
new_block = {}
|
||||||
|
|
||||||
|
return final_blocks
|
||||||
|
|
||||||
|
def _get_block_text(self, block):
|
||||||
|
return f"{block['number']}\n{block['time']}\n{block['text']}"
|
||||||
|
|
||||||
|
def _concat_blocks(self, sliced_text: str, text: str):
|
||||||
|
return f"{sliced_text}\n\n{text}" if sliced_text else text
|
||||||
|
|
||||||
|
def _get_block_translate(self, block):
|
||||||
|
return f"{block['number']}\n{block['text']}"
|
||||||
|
|
||||||
|
def _get_block_from(self, text):
|
||||||
|
text = text.strip()
|
||||||
|
if not text:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
block = text.split("\n")
|
||||||
|
if len(block) < 2:
|
||||||
|
return {"number": block[0], "text": ""}
|
||||||
|
|
||||||
|
return {"number": block[0], "text": "\n".join(block[1:])}
|
||||||
|
|
||||||
|
def _get_blocks_from(self, translate: str):
|
||||||
|
if not translate:
|
||||||
|
return []
|
||||||
|
|
||||||
|
blocks = []
|
||||||
|
blocks_text = translate.strip().split("\n\n")
|
||||||
|
for text in blocks_text:
|
||||||
|
blocks.append(self._get_block_from(text))
|
||||||
|
|
||||||
|
return blocks
|
||||||
|
|
||||||
|
def _check_blocks(self, translate_blocks, origin_blocks):
|
||||||
|
"""
|
||||||
|
Check if the translated blocks match the original text, with only a simple check of the beginning numbers.
|
||||||
|
"""
|
||||||
|
if len(translate_blocks) != len(origin_blocks):
|
||||||
|
return False
|
||||||
|
|
||||||
|
for t in zip(translate_blocks, origin_blocks):
|
||||||
|
i = 0
|
||||||
|
try:
|
||||||
|
i = int(t[0].get("number", 0))
|
||||||
|
except ValueError:
|
||||||
|
m = re.search(r"\s*\d+", t[0].get("number"))
|
||||||
|
if m:
|
||||||
|
i = int(m.group())
|
||||||
|
|
||||||
|
j = int(t[1].get("number", -1))
|
||||||
|
if i != j:
|
||||||
|
print(f"check failed: {i}!={j}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _get_sliced_list(self):
|
||||||
|
sliced_list = []
|
||||||
|
sliced_text = ""
|
||||||
|
begin_index = 0
|
||||||
|
for i, block in enumerate(self.blocks):
|
||||||
|
text = self._get_block_translate(block)
|
||||||
|
if not text:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if len(sliced_text + text) < self.accumulated_num:
|
||||||
|
sliced_text = self._concat_blocks(sliced_text, text)
|
||||||
|
else:
|
||||||
|
if sliced_text:
|
||||||
|
sliced_list.append((begin_index, i, sliced_text))
|
||||||
|
sliced_text = text
|
||||||
|
begin_index = i
|
||||||
|
|
||||||
|
sliced_list.append((begin_index, len(self.blocks), sliced_text))
|
||||||
|
return sliced_list
|
||||||
|
|
||||||
|
def make_bilingual_book(self):
|
||||||
|
if self.accumulated_num > 512:
|
||||||
|
print(f"{self.accumulated_num} is too large, shrink it to 512.")
|
||||||
|
self.accumulated_num = 512
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(f"{self.srt_name}", encoding="utf-8") as f:
|
||||||
|
self.blocks = self._parse_srt(f.read())
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("can not load file") from e
|
||||||
|
|
||||||
|
index = 0
|
||||||
|
p_to_save_len = len(self.p_to_save)
|
||||||
|
|
||||||
|
try:
|
||||||
|
sliced_list = self._get_sliced_list()
|
||||||
|
|
||||||
|
for sliced in sliced_list:
|
||||||
|
begin, end, text = sliced
|
||||||
|
|
||||||
|
if not self.resume or index + (end - begin) > p_to_save_len:
|
||||||
|
if index < p_to_save_len:
|
||||||
|
self.p_to_save = self.p_to_save[:index]
|
||||||
|
|
||||||
|
try:
|
||||||
|
temp = self.translate_model.translate(text)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
raise Exception("Something is wrong when translate") from e
|
||||||
|
|
||||||
|
translated_blocks = self._get_blocks_from(temp)
|
||||||
|
|
||||||
|
if self.accumulated_num > 1:
|
||||||
|
if not self._check_blocks(
|
||||||
|
translated_blocks, self.blocks[begin:end]
|
||||||
|
):
|
||||||
|
translated_blocks = []
|
||||||
|
# try to translate one by one, so don't accumulate too much
|
||||||
|
print(
|
||||||
|
f"retry it one by one: {self.blocks[begin]['number']} - {self.blocks[end-1]['number']}"
|
||||||
|
)
|
||||||
|
for block in self.blocks[begin:end]:
|
||||||
|
try:
|
||||||
|
temp = self.translate_model.translate(
|
||||||
|
self._get_block_translate(block)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
raise Exception(
|
||||||
|
"Something is wrong when translate"
|
||||||
|
) from e
|
||||||
|
translated_blocks.append(self._get_block_from(temp))
|
||||||
|
|
||||||
|
if not self._check_blocks(
|
||||||
|
translated_blocks, self.blocks[begin:end]
|
||||||
|
):
|
||||||
|
raise Exception(
|
||||||
|
f"retry failed, adjust the srt manually."
|
||||||
|
)
|
||||||
|
|
||||||
|
for i, block in enumerate(translated_blocks):
|
||||||
|
text = block.get("text", "")
|
||||||
|
self.p_to_save.append(text)
|
||||||
|
self.bilingual_result.append(
|
||||||
|
f"{self._get_block_text(self.blocks[begin + i])}\n{text}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
for i, block in enumerate(self.blocks[begin:end]):
|
||||||
|
text = self.p_to_save[begin + i]
|
||||||
|
self.bilingual_result.append(
|
||||||
|
f"{self._get_block_text(self.blocks[begin + i])}\n{text}"
|
||||||
|
)
|
||||||
|
|
||||||
|
index += end - begin
|
||||||
|
if self.is_test and index > self.test_num:
|
||||||
|
break
|
||||||
|
|
||||||
|
self.save_file(
|
||||||
|
f"{Path(self.srt_name).parent}/{Path(self.srt_name).stem}_bilingual.srt",
|
||||||
|
self.bilingual_result,
|
||||||
|
)
|
||||||
|
|
||||||
|
except (KeyboardInterrupt, Exception) as e:
|
||||||
|
print(e)
|
||||||
|
print("you can resume it next time")
|
||||||
|
self._save_progress()
|
||||||
|
self._save_temp_book()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def _save_temp_book(self):
|
||||||
|
for i, block in enumerate(self.blocks):
|
||||||
|
if i < len(self.p_to_save):
|
||||||
|
text = self.p_to_save[i]
|
||||||
|
self.bilingual_temp_result.append(
|
||||||
|
f"{self._get_block_text(block)}\n{text}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.bilingual_temp_result.append(f"{self._get_block_text(block)}\n")
|
||||||
|
|
||||||
|
self.save_file(
|
||||||
|
f"{Path(self.srt_name).parent}/{Path(self.srt_name).stem}_bilingual_temp.srt",
|
||||||
|
self.bilingual_temp_result,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _save_progress(self):
|
||||||
|
try:
|
||||||
|
with open(self.bin_path, "w", encoding="utf-8") as f:
|
||||||
|
f.write("===".join(self.p_to_save))
|
||||||
|
except:
|
||||||
|
raise Exception("can not save resume file")
|
||||||
|
|
||||||
|
def load_state(self):
|
||||||
|
try:
|
||||||
|
with open(self.bin_path, encoding="utf-8") as f:
|
||||||
|
text = f.read()
|
||||||
|
if text:
|
||||||
|
self.p_to_save = text.split("===")
|
||||||
|
else:
|
||||||
|
self.p_to_save = []
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("can not load resume file") from e
|
||||||
|
|
||||||
|
def save_file(self, book_path, content):
|
||||||
|
try:
|
||||||
|
with open(book_path, "w", encoding="utf-8") as f:
|
||||||
|
f.write("\n\n".join(content))
|
||||||
|
except:
|
||||||
|
raise Exception("can not save file")
|
||||||
|
440
test_books/Lex_Fridman_episode_322.srt
Normal file
440
test_books/Lex_Fridman_episode_322.srt
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
1
|
||||||
|
00:00:00,000 --> 00:00:07,040
|
||||||
|
there's a broader question here, right? As we build socially and emotionally intelligent machines,
|
||||||
|
|
||||||
|
2
|
||||||
|
00:00:07,920 --> 00:00:12,640
|
||||||
|
what does that mean about our relationship with them and then more broadly our relationship with
|
||||||
|
|
||||||
|
3
|
||||||
|
00:00:12,640 --> 00:00:18,240
|
||||||
|
one another, right? Because this machine is going to be programmed to be amazing at empathy,
|
||||||
|
|
||||||
|
4
|
||||||
|
00:00:18,240 --> 00:00:22,560
|
||||||
|
by definition, right? It's going to always be there for you. It's not going to get bored.
|
||||||
|
|
||||||
|
5
|
||||||
|
00:00:23,440 --> 00:00:25,680
|
||||||
|
I don't know how I feel about that. I think about that a lot.
|
||||||
|
|
||||||
|
6
|
||||||
|
00:00:25,680 --> 00:00:30,320
|
||||||
|
TITO The following is a conversation with Rana
|
||||||
|
|
||||||
|
7
|
||||||
|
00:00:30,320 --> 00:00:36,080
|
||||||
|
L. Kliubi, a pioneer in the field of emotion recognition and human centric artificial
|
||||||
|
|
||||||
|
8
|
||||||
|
00:00:36,080 --> 00:00:43,920
|
||||||
|
intelligence. She is the founder of Effectiva, deputy CEO of SmartEye, author of Girl Decoded,
|
||||||
|
|
||||||
|
9
|
||||||
|
00:00:43,920 --> 00:00:49,200
|
||||||
|
and one of the most brilliant, kind, inspiring, and fun human beings I've gotten the chance to
|
||||||
|
|
||||||
|
10
|
||||||
|
00:00:49,200 --> 00:00:54,800
|
||||||
|
talk to. This is the Lex Friedman podcast. To support it, please check out our sponsors in
|
||||||
|
|
||||||
|
11
|
||||||
|
00:00:54,800 --> 00:01:02,400
|
||||||
|
the description. And now, dear friends, here's Rana L. Kliubi. You grew up in the Middle East,
|
||||||
|
|
||||||
|
12
|
||||||
|
00:01:02,400 --> 00:01:08,000
|
||||||
|
in Egypt. What is the memory from that time that makes you smile? Or maybe a memory that stands out
|
||||||
|
|
||||||
|
13
|
||||||
|
00:01:08,000 --> 00:01:12,320
|
||||||
|
as helping your mind take shape and helping you define yourself in this world?
|
||||||
|
|
||||||
|
14
|
||||||
|
00:01:12,320 --> 00:01:15,440
|
||||||
|
RANA L. KLIUBI So the memory that stands out is we used to
|
||||||
|
|
||||||
|
15
|
||||||
|
00:01:15,440 --> 00:01:21,680
|
||||||
|
live in my grandma's house. She used to have these mango trees in her garden. And in the summer,
|
||||||
|
|
||||||
|
16
|
||||||
|
00:01:21,680 --> 00:01:26,640
|
||||||
|
and so mango season was like July and August. And so in the summer, she would invite all my aunts
|
||||||
|
|
||||||
|
17
|
||||||
|
00:01:26,640 --> 00:01:31,680
|
||||||
|
and uncles and cousins. And it was just like maybe there were like 20 or 30 people in the house,
|
||||||
|
|
||||||
|
18
|
||||||
|
00:01:31,680 --> 00:01:38,080
|
||||||
|
and she would cook all this amazing food. And us, the kids, we would go down the garden,
|
||||||
|
|
||||||
|
19
|
||||||
|
00:01:38,080 --> 00:01:43,920
|
||||||
|
and we would pick all these mangoes. And I don't know, I think it's just the bringing people
|
||||||
|
|
||||||
|
20
|
||||||
|
00:01:43,920 --> 00:01:47,920
|
||||||
|
together that always stuck with me, the warmth. TITO Around the mango tree.
|
||||||
|
|
||||||
|
21
|
||||||
|
00:01:47,920 --> 00:01:52,800
|
||||||
|
RANA L. KLIUBI Yeah, around the mango tree. And there's just like the joy, the joy of being
|
||||||
|
|
||||||
|
22
|
||||||
|
00:01:52,800 --> 00:02:00,880
|
||||||
|
together around food. And I'm a terrible cook. So I guess that didn't, that memory didn't translate
|
||||||
|
|
||||||
|
23
|
||||||
|
00:02:00,880 --> 00:02:05,520
|
||||||
|
to me kind of doing the same. I love hosting people. TITO Do you remember colors, smells?
|
||||||
|
|
||||||
|
24
|
||||||
|
00:02:05,520 --> 00:02:10,560
|
||||||
|
Is that what, like what, how does memory work? Like what do you visualize? Do you visualize
|
||||||
|
|
||||||
|
25
|
||||||
|
00:02:10,560 --> 00:02:19,360
|
||||||
|
people's faces, smiles? Do you, is there colors? Is there like a theme to the colors? Is it smells
|
||||||
|
|
||||||
|
26
|
||||||
|
00:02:19,360 --> 00:02:23,360
|
||||||
|
because of food involved? RANA L. KLIUBI Yeah, I think that's a great question. So the,
|
||||||
|
|
||||||
|
27
|
||||||
|
00:02:23,360 --> 00:02:28,800
|
||||||
|
those Egyptian mangoes, there's a particular type that I love, and it's called Darwasi mangoes. And
|
||||||
|
|
||||||
|
28
|
||||||
|
00:02:28,800 --> 00:02:33,680
|
||||||
|
they're kind of, you know, they're oval, and they have a little red in them. So I kind of,
|
||||||
|
|
||||||
|
29
|
||||||
|
00:02:33,680 --> 00:02:39,600
|
||||||
|
they're red and mango colored on the outside. So I remember that. TITO Does red indicate like
|
||||||
|
|
||||||
|
30
|
||||||
|
00:02:39,600 --> 00:02:45,520
|
||||||
|
extra sweetness? Is that, is that, that means like it's nicely, yeah, it's nice and ripe and stuff.
|
||||||
|
|
||||||
|
31
|
||||||
|
00:02:45,520 --> 00:02:52,640
|
||||||
|
Yeah. What, what's like a definitive food of Egypt? You know, there's like these almost
|
||||||
|
|
||||||
|
32
|
||||||
|
00:02:52,640 --> 00:02:58,800
|
||||||
|
stereotypical foods in different parts of the world, like Ukraine invented borscht.
|
||||||
|
|
||||||
|
33
|
||||||
|
00:02:59,600 --> 00:03:04,800
|
||||||
|
Borscht is this beet soup with, that you put sour cream on. See, it's not, I can't see if you,
|
||||||
|
|
||||||
|
34
|
||||||
|
00:03:04,800 --> 00:03:10,880
|
||||||
|
if you know, if you know what it is, I think, you know, is delicious. But if I explain it,
|
||||||
|
|
||||||
|
35
|
||||||
|
00:03:10,880 --> 00:03:15,280
|
||||||
|
it's just not going to sound delicious. I feel like beet soup. This doesn't make any sense,
|
||||||
|
|
||||||
|
36
|
||||||
|
00:03:15,280 --> 00:03:19,600
|
||||||
|
but that's kind of, and you probably have actually seen pictures of it because it's one of the
|
||||||
|
|
||||||
|
37
|
||||||
|
00:03:19,600 --> 00:03:26,800
|
||||||
|
traditional foods in Ukraine, in Russia, in different parts of the Slavic world. So that's,
|
||||||
|
|
||||||
|
38
|
||||||
|
00:03:26,800 --> 00:03:31,520
|
||||||
|
but it's become so cliche and stereotypical that you almost don't mention it, but it's still
|
||||||
|
|
||||||
|
39
|
||||||
|
00:03:31,520 --> 00:03:35,440
|
||||||
|
delicious. Like I visited Ukraine, I eat that every single day, so.
|
||||||
|
|
||||||
|
40
|
||||||
|
00:03:35,440 --> 00:03:38,480
|
||||||
|
Do you, do you make it yourself? How hard is it to make?
|
||||||
|
|
||||||
|
41
|
||||||
|
00:03:38,480 --> 00:03:43,600
|
||||||
|
No, I don't know. I think to make it well, like anything, like Italians, they say, well,
|
||||||
|
|
||||||
|
42
|
||||||
|
00:03:44,320 --> 00:03:51,760
|
||||||
|
tomato sauce is easy to make, but to make it right, that's like a generational skill. So anyway,
|
||||||
|
|
||||||
|
43
|
||||||
|
00:03:51,760 --> 00:03:55,200
|
||||||
|
is there something like that in Egypt? Is there a culture of food?
|
||||||
|
|
||||||
|
44
|
||||||
|
00:03:55,200 --> 00:04:02,880
|
||||||
|
There is. And actually, we have a similar kind of soup. It's called molokhia, and it's, it's made
|
||||||
|
|
||||||
|
45
|
||||||
|
00:04:02,880 --> 00:04:07,520
|
||||||
|
of this green plant. It's like, it's somewhere between spinach and kale, and you mince it,
|
||||||
|
|
||||||
|
46
|
||||||
|
00:04:07,520 --> 00:04:13,360
|
||||||
|
and then you cook it in like chicken broth. And my grandma used to make, and my mom makes it really
|
||||||
|
|
||||||
|
47
|
||||||
|
00:04:13,360 --> 00:04:18,080
|
||||||
|
well, and I try to make it, but it's not as great. So we used to have that. And then we used to have
|
||||||
|
|
||||||
|
48
|
||||||
|
00:04:18,080 --> 00:04:23,520
|
||||||
|
it alongside stuffed pigeons. I'm pescetarian now, so I don't eat that anymore, but.
|
||||||
|
|
||||||
|
49
|
||||||
|
00:04:23,520 --> 00:04:24,480
|
||||||
|
Stuffed pigeons.
|
||||||
|
|
||||||
|
50
|
||||||
|
00:04:24,480 --> 00:04:27,600
|
||||||
|
Yeah, it's like, it was really yummy. It's the one thing I miss about,
|
||||||
|
|
||||||
|
51
|
||||||
|
00:04:28,480 --> 00:04:32,080
|
||||||
|
you know, now that I'm pescetarian and I don't eat.
|
||||||
|
|
||||||
|
52
|
||||||
|
00:04:32,080 --> 00:04:33,040
|
||||||
|
The stuffed pigeons?
|
||||||
|
|
||||||
|
53
|
||||||
|
00:04:33,040 --> 00:04:34,240
|
||||||
|
Yeah, the stuffed pigeons.
|
||||||
|
|
||||||
|
54
|
||||||
|
00:04:35,440 --> 00:04:39,920
|
||||||
|
Is it, what are they stuffed with? If that doesn't bother you too much to describe.
|
||||||
|
|
||||||
|
55
|
||||||
|
00:04:39,920 --> 00:04:46,000
|
||||||
|
No, no, it's stuffed with a lot of like just rice and, yeah, it's just rice. Yeah, so.
|
||||||
|
|
||||||
|
56
|
||||||
|
00:04:46,000 --> 00:04:51,120
|
||||||
|
And you also, you said that your first, in your book, that your first computer
|
||||||
|
|
||||||
|
57
|
||||||
|
00:04:51,120 --> 00:04:54,880
|
||||||
|
was an Atari, and Space Invaders was your favorite game.
|
||||||
|
|
||||||
|
58
|
||||||
|
00:04:56,000 --> 00:04:58,800
|
||||||
|
Is that when you first fell in love with computers, would you say?
|
||||||
|
|
||||||
|
59
|
||||||
|
00:04:58,800 --> 00:05:00,160
|
||||||
|
Yeah, I would say so.
|
||||||
|
|
||||||
|
60
|
||||||
|
00:05:00,160 --> 00:05:04,160
|
||||||
|
Video games, or just the computer itself? Just something about the machine.
|
||||||
|
|
||||||
|
61
|
||||||
|
00:05:04,160 --> 00:05:07,840
|
||||||
|
Ooh, this thing, there's magic in here.
|
||||||
|
|
||||||
|
62
|
||||||
|
00:05:07,840 --> 00:05:12,080
|
||||||
|
Yeah, I think the magical moment is definitely like playing video games with my,
|
||||||
|
|
||||||
|
63
|
||||||
|
00:05:12,080 --> 00:05:17,120
|
||||||
|
I have two younger sisters, and we would just like had fun together, like playing games.
|
||||||
|
|
||||||
|
64
|
||||||
|
00:05:17,120 --> 00:05:22,240
|
||||||
|
But the other memory I have is my first code, the first code I wrote.
|
||||||
|
|
||||||
|
65
|
||||||
|
00:05:22,240 --> 00:05:26,720
|
||||||
|
I wrote, I drew a Christmas tree, and I'm Muslim, right?
|
||||||
|
|
||||||
|
66
|
||||||
|
00:05:26,720 --> 00:05:32,000
|
||||||
|
So it's kind of, it was kind of funny that the first thing I did was like this Christmas tree.
|
||||||
|
|
||||||
|
67
|
||||||
|
00:05:32,000 --> 00:05:38,320
|
||||||
|
So, yeah, and that's when I realized, wow, you can write code to do all sorts of like
|
||||||
|
|
||||||
|
68
|
||||||
|
00:05:38,320 --> 00:05:42,720
|
||||||
|
really cool stuff. I must have been like six or seven at the time.
|
||||||
|
|
||||||
|
69
|
||||||
|
00:05:42,720 --> 00:05:48,560
|
||||||
|
So you can write programs, and the programs do stuff for you. That's power.
|
||||||
|
|
||||||
|
70
|
||||||
|
00:05:48,560 --> 00:05:50,880
|
||||||
|
That's, if you think about it, that's empowering.
|
||||||
|
|
||||||
|
71
|
||||||
|
00:05:50,880 --> 00:05:51,600
|
||||||
|
It's AI.
|
||||||
|
|
||||||
|
72
|
||||||
|
00:05:51,600 --> 00:05:55,120
|
||||||
|
Yeah, I know what it is. I don't know if that, you see like,
|
||||||
|
|
||||||
|
73
|
||||||
|
00:05:56,400 --> 00:05:59,520
|
||||||
|
I don't know if many people think of it that way when they first learned to program.
|
||||||
|
|
||||||
|
74
|
||||||
|
00:05:59,520 --> 00:06:02,880
|
||||||
|
They just love the puzzle of it. Like, ooh, this is cool. This is pretty.
|
||||||
|
|
||||||
|
75
|
||||||
|
00:06:02,880 --> 00:06:05,600
|
||||||
|
It's a Christmas tree, but like, it's power.
|
||||||
|
|
||||||
|
76
|
||||||
|
00:06:05,600 --> 00:06:06,960
|
||||||
|
It is power.
|
||||||
|
|
||||||
|
77
|
||||||
|
00:06:06,960 --> 00:06:11,040
|
||||||
|
Eventually, I guess you couldn't at the time, but eventually this thing,
|
||||||
|
|
||||||
|
78
|
||||||
|
00:06:11,040 --> 00:06:14,640
|
||||||
|
if it's interesting enough, if it's a pretty enough Christmas tree,
|
||||||
|
|
||||||
|
79
|
||||||
|
00:06:14,640 --> 00:06:19,280
|
||||||
|
it can be run by millions of people and bring them joy, like that little thing.
|
||||||
|
|
||||||
|
80
|
||||||
|
00:06:19,280 --> 00:06:21,760
|
||||||
|
And then because it's digital, it's easy to spread.
|
||||||
|
|
||||||
|
81
|
||||||
|
00:06:22,400 --> 00:06:26,560
|
||||||
|
So like you just created something that's easily spreadable to millions of people.
|
||||||
|
|
||||||
|
82
|
||||||
|
00:06:26,560 --> 00:06:27,120
|
||||||
|
Totally.
|
||||||
|
|
||||||
|
83
|
||||||
|
00:06:28,160 --> 00:06:29,840
|
||||||
|
It's hard to think that way when you're six.
|
||||||
|
|
||||||
|
84
|
||||||
|
00:06:30,800 --> 00:06:37,040
|
||||||
|
In the book, you write, I am who I am because I was raised by a particular set of parents,
|
||||||
|
|
||||||
|
85
|
||||||
|
00:06:37,040 --> 00:06:41,200
|
||||||
|
both modern and conservative, forward thinking, yet locked in tradition.
|
||||||
|
|
||||||
|
86
|
||||||
|
00:06:41,760 --> 00:06:46,000
|
||||||
|
I'm a Muslim and I feel I'm stronger, more centered for it.
|
||||||
|
|
||||||
|
87
|
||||||
|
00:06:46,000 --> 00:06:50,960
|
||||||
|
I adhere to the values of my religion, even if I'm not as dutiful as I once was.
|
||||||
|
|
||||||
|
88
|
||||||
|
00:06:50,960 --> 00:06:55,040
|
||||||
|
And I am a new American and I'm thriving on the energy,
|
||||||
|
|
||||||
|
89
|
||||||
|
00:06:55,040 --> 00:06:58,720
|
||||||
|
vitality and entrepreneurial spirit of this great country.
|
||||||
|
|
||||||
|
90
|
||||||
|
00:06:59,840 --> 00:07:01,520
|
||||||
|
So let me ask you about your parents.
|
||||||
|
|
||||||
|
91
|
||||||
|
00:07:01,520 --> 00:07:05,280
|
||||||
|
What have you learned about life from them, especially when you were young?
|
||||||
|
|
||||||
|
92
|
||||||
|
00:07:05,280 --> 00:07:09,920
|
||||||
|
So both my parents, they're Egyptian, but they moved to Kuwait right out.
|
||||||
|
|
||||||
|
93
|
||||||
|
00:07:09,920 --> 00:07:11,680
|
||||||
|
Actually, there's a cute story about how they met.
|
||||||
|
|
||||||
|
94
|
||||||
|
00:07:11,680 --> 00:07:14,960
|
||||||
|
So my dad taught COBOL in the 70s.
|
||||||
|
|
||||||
|
95
|
||||||
|
00:07:14,960 --> 00:07:15,680
|
||||||
|
Nice.
|
||||||
|
|
||||||
|
96
|
||||||
|
00:07:15,680 --> 00:07:18,240
|
||||||
|
And my mom decided to learn programming.
|
||||||
|
|
||||||
|
97
|
||||||
|
00:07:18,240 --> 00:07:21,120
|
||||||
|
So she signed up to take his COBOL programming class.
|
||||||
|
|
||||||
|
98
|
||||||
|
00:07:22,400 --> 00:07:26,640
|
||||||
|
And he tried to date her and she was like, no, no, no, I don't date.
|
||||||
|
|
||||||
|
99
|
||||||
|
00:07:26,640 --> 00:07:28,240
|
||||||
|
And so he's like, okay, I'll propose.
|
||||||
|
|
||||||
|
100
|
||||||
|
00:07:28,240 --> 00:07:29,680
|
||||||
|
And that's how they got married.
|
||||||
|
|
||||||
|
101
|
||||||
|
00:07:29,680 --> 00:07:30,960
|
||||||
|
Whoa, strong move.
|
||||||
|
|
||||||
|
102
|
||||||
|
00:07:30,960 --> 00:07:32,240
|
||||||
|
Right, exactly, right.
|
||||||
|
|
||||||
|
103
|
||||||
|
00:07:32,240 --> 00:07:34,640
|
||||||
|
That's really impressive.
|
||||||
|
|
||||||
|
104
|
||||||
|
00:07:35,760 --> 00:07:38,800
|
||||||
|
Those COBOL guys know how to impress a lady.
|
||||||
|
|
||||||
|
105
|
||||||
|
00:07:40,640 --> 00:07:43,520
|
||||||
|
So yeah, so what have you learned from them?
|
||||||
|
|
||||||
|
106
|
||||||
|
00:07:43,520 --> 00:07:44,720
|
||||||
|
So definitely grit.
|
||||||
|
|
||||||
|
107
|
||||||
|
00:07:44,720 --> 00:07:47,360
|
||||||
|
One of the core values in our family is just hard work.
|
||||||
|
|
||||||
|
108
|
||||||
|
00:07:48,320 --> 00:07:50,080
|
||||||
|
There were no slackers in our family.
|
||||||
|
|
||||||
|
109
|
||||||
|
00:07:50,720 --> 00:07:54,160
|
||||||
|
And that's something that's definitely stayed with me,
|
||||||
|
|
||||||
|
110
|
||||||
|
00:07:55,920 --> 00:07:58,480
|
||||||
|
both as a professional, but also in my personal life.
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user