Emoto AI is a voice-first companion assistant for a young Indonesian learner named Alfian. Emoto greets him aloud when it starts, listens to him speak Indonesian through a microphone, answers aloud, reads text out of photos and video files, and offers encouragement and explanations on school subjects. The product intent is a friendly, patient, slightly wonder-filled tutor that lives in the room with the learner — warmth, wellbeing and trust matter more than density or dashboards.
The audience is Alfian (Pelajar Pengguna Emoto), a student who interacts with Emoto by choosing a numbered menu option, supplying a spoken question or a local file name, and hearing and reading Emoto's spoken answer. The interface is a warm, human-scale surface: an oat ground, sage structure, and a single terracotta signal, with the assistant represented by a breathing ring and a waveform rather than a robot illustration.
Emoto AI is delivered as a first-party application with custom UI. It runs as a single local assistant session: on start it speaks a greeting, then repeatedly presents the main menu, accepts a numbered choice, performs the selected capability, and returns to the menu until the user chooses to exit.
Current accepted behavior:
id-ID), and lowercases the result. Unrecognized speech returns tidak terdengar; a recognition service error returns koneksi bermasalah. Both cases produce a spoken retry message.siapa kamu / siapa kau, siapa namamu, and terima kasih each receive a specific spoken reply; any other utterance is echoed back with an offer of further help.lang='ind'), and speaks the extracted text; if no text is found it says so; on error it reports the problem.lang='ind'), and speaks the extracted text; if no clear text is found it says so; if the file cannot be opened or an error occurs it reports the problem.matematika, bahasa, ipa, and ips, and speaks the matching encouragement; when no topic matches it falls back to a default encouraging answer.Actors: one accepted human persona, Alfian (Pelajar Pengguna Emoto). The speech-recognition service and the text-to-speech engine are non-persona system/provider actors that Emoto depends on.
Narrow exclusions: study help is limited to the four built-in topics plus a default answer; video reading processes a single frame from the file; photo and video inputs are supplied as local file names entered by the user.
Emoto AI is a local, single-user assistant. All six accepted destinations are first-party custom pages owned by the application, and all of them are reachable without any account: the source establishes no sign-in, no profile, no stored history, and no cross-session continuity requirement. Identity is therefore not application-owned — Emoto addresses Alfian by name because the source names him, not because a login binds the session to him. No account creation, invitation, provisioning, or session-resume capability is part of the current product.
Delivery is a running assistant session rather than a hosted multi-tenant service. The microphone, the local photo and video files, the Indonesian speech-recognition availability, the Indonesian OCR language data, and the text-to-speech engine are all prerequisites of the accepted journeys and are treated as required inferences, not as new capabilities. The speech-recognition service is an external provider dependency; the text-to-speech engine and OCR run locally.
Current boundary: the five numbered capabilities, the greeting, the farewell, and the invalid-choice handling. Future boundary: nothing beyond the accepted thread is committed; no additional subjects, no multi-frame video scanning, no remote file sources, and no account features are in scope.
The authoritative source supplies the built-in study-help knowledge base. These are the exact topics and their exact encouragement texts, and they must be preserved verbatim.
| Topic key | Spoken encouragement |
|---|---|
matematika | "Matematika itu seperti melatih otot otak. Mulai dari yang mudah, latihan setiap hari sedikit saja, lama-lama pasti makin pintar. Jangan menyerah ya!" |
bahasa | "Belajar bahasa itu seperti mengenal dunia baru. Banyak membaca, mendengarkan, dan mencoba berbicara. Kesalahan adalah cara belajar yang terbaik." |
ipa | "Ilmu Pengetahuan Alam menjelaskan bagaimana alam semesta bekerja. Amati, tanyakan, dan cari jawabannya. Semangat peneliti muda!" |
ips | "Ilmu Pengetahuan Sosial mengajarkan kita bagaimana hidup bersama, saling menghargai, dan memahami sesama." |
default | "Teruslah bertanya dan belajar, Alfian. Setiap pertanyaan adalah langkah menuju kebijaksanaan. Kalau ada yang sulit, pelan-pelan pasti bisa!" |
The source also supplies the exact spoken strings used by the assistant:
| Context | Exact spoken text |
|---|---|
| Startup greeting | "Halo! Aku Emoto, teman pintarmu! Siap membantu kapan saja!" |
| Voice prompt | "Silakan, aku mendengarkan!" |
Identity reply (siapa kamu / siapa kau) | "Aku Emoto, teman buatanmu yang siap membantu dan menemani kamu setiap hari!" |
Courtesy reply (terima kasih) | "Sama-sama! Aku senang bisa membantu kamu!" |
Name reply (siapa namamu) | "Namaku Emoto, dan aku bangga jadi temanmu, Alfian!" |
| Generic echo reply | "Kamu berkata: {ucapan}. Ada yang bisa kubantu lebih lanjut?" |
| Unclear-speech retry | "Maaf, aku belum mendengar dengan jelas. Coba lagi ya." |
| Photo, no text found | "Maaf, aku tidak menemukan teks di foto itu." |
| Photo, success prefix | "Isi teks di foto: {teks}" |
| Photo, error | "Maaf, ada masalah saat membaca foto: {str(e)}" |
| Video, no clear text | "Aku sudah lihat satu bagian dari videonya, tapi belum menemukan teks yang jelas." |
| Video, success prefix | "Aku membaca di videomu: {teks}" |
| Video, cannot open | "Maaf, aku tidak bisa membuka file videonya." |
| Video, error | "Maaf, ada masalah saat membaca video: {str(e)}" |
| Farewell | "Sampai jumpa, Alfian! Semangat terus ya, aku selalu siap di sini kapan pun kamu butuh. Selamat beraktivitas!" |
| Invalid choice | "Pilihan belum tersedia, coba pilih nomor 1 sampai 5 ya." |
The main menu presents exactly these five numbered options:
1.\x20\xf0\x9f\x8e\xa7 Bicara dan bertanya lewat suara 2.\x20\xf0\x9f\x93\xb8 Baca teks dari foto 3.\x20\xf0\x9f\x8e\xac Baca teks dari file video 4.\x20\xf0\x9f\x93\x9a Minta bantuan belajar 5.\x20\xe2\x9d\x8c Keluar dari Emoto
siapa kamu / siapa kau, siapa namamu, terima kasih, or generic), spoken reply.tidak terdengar or koneksi bermasalah produces the spoken retry message "Maaf, aku belum mendengar dengan jelas. Coba lagi ya." Recovery — the user speaks again; the ring returns to its listening state.FR-1 — Spoken greeting on start (explicit) As Alfian (Pelajar Pengguna Emoto), I should hear Emoto greet me aloud when the program starts, so that I know the assistant is ready.
FR-2 — Main menu with five numbered options (explicit) As Alfian, I should see a main menu with five numbered options, so that I can choose what Emoto does next.
FR-3 — Voice conversation with Indonesian recognition (explicit) As Alfian, I should speak into the microphone and have Emoto recognize my Indonesian speech and answer aloud, so that I can ask questions by voice.
id-ID, prints "\xe2\x8f\xb3 Sedang memproses..." then "\xf0\x9f\x91\xa4 Kamu: {hasil}", lowercases the result, and speaks a reply.sr.UnknownValueError returns tidak terdengar and sr.RequestError returns koneksi bermasalah; either produces the spoken message "Maaf, aku belum mendengar dengan jelas. Coba lagi ya."FR-4 — Identity and courtesy intents (explicit) As Alfian, I should get a specific spoken reply when I ask who Emoto is, ask Emoto's name, or thank it, so that the conversation feels personal.
siapa kamu or siapa kau, siapa namamu, or terima kasih.siapa kamu / siapa kau → "Aku Emoto, teman buatanmu yang siap membantu dan menemani kamu setiap hari!"; siapa namamu → "Namaku Emoto, dan aku bangga jadi temanmu, Alfian!"; terima kasih → "Sama-sama! Aku senang bisa membantu kamu!".tidak terdengar or koneksi bermasalah, the retry message is spoken instead.FR-5 — Generic echo reply (explicit) As Alfian, I should hear my own words echoed back with an offer of further help when my utterance matches no specific intent, so that Emoto always responds.
FR-6 — Photo text reading (explicit) As Alfian, I should give Emoto a photo file name and hear the Indonesian text read out of that photo, so that I can have printed material read aloud.
lang='ind', and speaks the result with the prefix "Isi teks di foto: {teks}".FR-7 — Video text reading (explicit) As Alfian, I should give Emoto a video file name and hear the Indonesian text read out of a frame of that video, so that I can have on-screen text read aloud.
lang='ind', releases the video, and speaks the result with the prefix "Aku membaca di videomu: {teks}".FR-8 — Study help on built-in topics (explicit) As Alfian, I should name a topic and hear Emoto's encouragement for matematika, bahasa, ipa, or ips, so that I get support with my school subjects.
FR-9 — Default study-help answer (explicit) As Alfian, I should still get an encouraging answer when my topic matches none of the four built-in subjects, so that I am never left without a response.
matematika, bahasa, ipa, ips.FR-10 — Exit with farewell (explicit) As Alfian, I should be able to leave Emoto and hear a farewell, so that the session ends warmly.
FR-11 — Invalid menu choice handling (explicit) As Alfian, I should be told to pick 1 through 5 when I enter something else, so that I can correct my choice.
FR-12 — Spoken output configuration (explicit) As Alfian, I should hear every Emoto response at a consistent, comfortable pace and volume, so that the assistant is easy to listen to.
FR-13 — Local microphone capture (required_inference) As Alfian, I should have Emoto open my local microphone and adjust for ambient noise before listening, so that my speech is captured reliably.
FR-14 — Indonesian speech-recognition availability (required_inference) As Alfian, I should have my Indonesian speech recognized, so that I can speak naturally rather than in another language.
id-ID and returns lowercased Indonesian text.koneksi bermasalah and the retry message is spoken.FR-15 — Indonesian OCR language data (required_inference) As Alfian, I should have Indonesian text recognized inside my photos and videos, so that the extracted text is in the language I read.
lang='ind' and returns Indonesian text.FR-16 — Local photo and video file availability (required_inference) As Alfian, I should be able to point Emoto at a photo or video file on my machine by name, so that Emoto can read it.
Product context. Alfian is a student who uses Emoto AI as a nearby companion for schoolwork and everyday reading. Emoto addresses him by name in its greeting, its name reply, its default study-help answer, and its farewell, so the product is built around a single known learner rather than an anonymous crowd. He works in Indonesian and expects Emoto to understand and answer in Indonesian.
Primary goal. To get a clear spoken answer — whether that is a reply to something he asked out loud, the text hidden inside a photo or a video frame, or encouragement on a school subject — and then to move on or exit.
Distinct accepted responsibilities.
Relevant inputs and decisions. He supplies a menu number, a spoken utterance, a photo file name, a video file name, or a study topic. His decisions are which capability to use, whether to retry after unclear speech, and when to exit.
Interactions with other accepted participants. Alfian is the only accepted human participant. His counterpart in every exchange is Emoto itself, whose replies are produced by the text-to-speech engine and whose listening depends on the Indonesian speech-recognition service. When recognition fails, the exchange is between Alfian and Emoto's retry message rather than a third party.
Observable success. He hears a spoken reply that matches what he asked for, sees the same reply printed as "\xf0\x9f\xa4\x96 Emoto: …", and can return to the menu or exit. For photo and video reading, success is hearing the extracted Indonesian text; for study help, success is hearing the encouragement for his subject or the default encouragement.
What makes this role different. Alfian is not an operator configuring a system and not a member of a team sharing state. He is a learner in a one-to-one spoken relationship with the assistant: his inputs are his own voice and his own local files, his outputs are things he hears, and nothing he does is visible to or shared with anyone else. There is no account, no role, and no permission to reason about — only the choice of what to ask Emoto next.
Failure/recovery: if the text-to-speech engine is unavailable, the greeting still appears as printed text and the menu is still presented, so Alfian can continue with any capability.
id-ID, prints "\xf0\x9f\x91\xa4 Kamu: {hasil}", and lowercases the result.Failure/recovery: if the speech is not recognized (tidak terdengar) or the recognition service is unreachable (koneksi bermasalah), Emoto speaks "Maaf, aku belum mendengar dengan jelas. Coba lagi ya." and the ring returns to its listening state so Alfian can try again.
siapa kamu or siapa kau, siapa namamu, or terima kasih.Failure/recovery: if the utterance is not recognized, the retry message from Flow 2 is spoken instead.
lang='ind') while the scan line sweeps top-to-bottom across the scan bed.Failure/recovery: if the photo contains no text, Emoto speaks "Maaf, aku tidak menemukan teks di foto itu."; if the file cannot be opened or another error occurs, Emoto speaks "Maaf, ada masalah saat membaca foto: {str(e)}". In both cases the scan bed returns to rest so Alfian can enter another file name.
lang='ind') while the scan line sweeps across the scan bed.Failure/recovery: if the frame contains no clear text, Emoto speaks "Aku sudah lihat satu bagian dari videonya, tapi belum menemukan teks yang jelas."; if the file cannot be opened, Emoto speaks "Maaf, aku tidak bisa membuka file videonya."; if another error occurs, Emoto speaks "Maaf, ada masalah saat membaca video: {str(e)}". In every case the scan bed returns to rest so Alfian can enter another file name.
matematika, bahasa, ipa, or ips.The creative direction is authoritative for this section. The muse is Yves Béhar, and the headline idea is "Humane technology — a warm voice that reads the world aloud." Emoto AI must never look like a generic AI SaaS landing page; the palette roles read instantly as oat ground, sage structure, and one terracotta signal.
Colour tokens (light mode).
| Role | Token | Hex |
|---|---|---|
| Background (warm oat ground) | --bg | #FAF6EF |
| Surface (cards, voice panels, felt) | --surface | #F1E9DC |
| Text (ink) | --text | #2B2622 |
| Primary (sage-slate structure) | --primary | #3F5B4E |
| Accent (terracotta signal) | --accent | #C4552D |
| Muted (captions, metadata) | --muted | #8A7F72 |
| Divider | --divider | #E4DACB |
| Shadow | --shadow | rgba(64,48,32,0.08), 24px blur |
Proportion: roughly 70% warm neutral ground, 20% sage structure, 10% terracotta signal — never more accent than that. Terracotta is reserved for the live microphone pulse, the active menu numeral, and the speaking waveform. Sage carries navigation, headers, and the listening ring at rest. Muted taupe is for captions and metadata only.
Typography.
-0.01em), sentence case, never all-caps shouting.Shape language. Soft, continuous, body-like curves: 28–40px radii on cards and voice panels, fully pill-shaped buttons and status chips, no sharp corners anywhere. The signature form is the listening ring — a thick rounded annulus that breathes between 1.0 and 1.06 scale. Dividers are 1px in #E4DACB, never heavy. Shadows are wide, low-opacity and warm-tinted so panels feel like objects resting on cloth, not floating glass.
Layout. Single-column, human-scale, generous: max 1120px content with 24px gutters at 375px and 64px at 1280px. The main menu is not a grid of identical cards — it is a vertical list of five wide capability rows, each a full-width rounded panel with an oversized Fraunces numeral on the left, a title, a one-line description, and a small state chip on the right; rows alternate a subtle oat/sage tint so the list reads as a sequence, not a grid. Voice, Photo Reader, Video Reader and Study Help each open as a focused single-task surface: one dominant object (the ring, the scan bed, the topic chips) centred with the transcript or result appearing below in a wide reading column.
Imagery. No stock people, no clip art, no gradient blobs. Imagery is tactile and material: softly lit still lifes of everyday learning objects on oat grounds (an open notebook, a school textbook, a photo print, a phone propped against a mug), shot with natural window light and shallow depth. Supporting graphics are warm flat diagrams — a sound wave, a page outline being scanned, a video frame with a text region marked — drawn in sage and terracotta line on oat. The assistant itself is never a robot illustration; it is represented by the breathing ring and the waveform.
Avoid. Blue or indigo primary on white; gradient-blob heroes, glassmorphism panels, or frosted translucent cards; a grid of identical hover-lift feature cards for the five menu options; robot mascots, cartoon androids, or emoji-as-illustration in the hero; sharp 0px corners, heavy drop shadows, or pure #FFFFFF grounds; bouncy or springy easing and any motion faster than 400ms on primary transitions; Inter, Roboto, Poppins or system-ui for headings or body copy; dense dashboard chrome, data tables, or sidebar navigation on the landing and menu surfaces.
Readable text and controls stay whole at every viewport. Headlines, wordmarks, labels, numbers, cards' text and controls stay entirely inside the viewport and their container at 375px, 768px and 1280px, wrapping or scaling (for example font-size: clamp(...) with its mobile size) to fit, and no other element covers any part of them. Imagery, decoration and motion may be cropped, bled off an edge, rotated, overlapped or cut exactly as the direction asks, as long as they cover no readable text or control. Where the direction asks a readable element to run off an edge, keep it whole and carry the gesture with imagery or decoration instead.
The breathing ring as the public entry. The Landing page is a warm oat (#FAF6EF) full-viewport first screen with no centred SaaS stack. Left-aligned in the upper-left third sits the wordmark "Emoto AI" small in Work Sans caps with wide tracking, and beneath it an oversized Fraunces headline at clamp(46px, 8vw, 96px) — "Aku mendengar. Aku bicara. Aku membacakan dunia untukmu." — spanning roughly 9 of 12 columns and allowed to run to the right edge of the container.
The dominant element is not the text but a large terracotta-and-sage breathing ring, 320px on desktop and 200px on mobile, bleeding off the lower-right of the viewport at about 15%, with a live waveform drawn across its lower arc. A small pill label "\xf0\x9f\x8e\xa7 Siap mendengarkan" sits inside the ring's centre and stays fully readable at every breakpoint. The primary CTA, a sage pill "Mulai bicara dengan Emoto", is pinned directly beneath the headline, flush left, with a secondary text link "atau lihat menu lengkap ↓". Beneath the fold edge, the first capability row peeks in to signal the sequence.
Nothing is centred, nothing floats in a blob, and the palette roles read instantly: oat ground, sage structure, one terracotta signal. The ring is the product's defining state made visible — it is the same object that listens on the Voice page, so the entry screen already teaches Alfian what Emoto looks like when it is paying attention.
Interaction Model: Animated Motion Tempo: restrained Hero Dimensionality: layered_2d
Landing Hero Motion Brief
cubic-bezier(0.22, 0.61, 0.36, 1) — the pace of a calm breath, never a bounce. Capability surfaces cross-fade in rather than sliding. Menu rows lift 3px and warm their tint on hover. Every loop is one purposeful loop.prefers-reduced-motion freezes the ring into a static filled circle with a text state label, stops the waveform, and disables the hover lift — the layout, the headline, the CTA, and the peeking capability row all remain fully usable and readable.NFR-1 — Indonesian speech recognition (explicit)
Speech recognition must be configured for Indonesian, language id-ID. Rationale: the accepted voice journey is conducted in Indonesian and the source fixes this language code.
NFR-2 — Indonesian OCR language data (explicit)
OCR must be performed with Indonesian language data, lang='ind'. Rationale: the accepted photo and video journeys extract Indonesian text and the source fixes this language code.
NFR-3 — Speech output configuration (explicit) Speech output must use pyttsx3 with rate 175 and volume 1.0. Rationale: the source fixes these values as the assistant's speaking pace and volume.
NFR-4 — Local file-name inputs (explicit) Photo and video inputs must be supplied as local file names entered by the user. Rationale: the source accepts a file name string and opens it directly; no upload, URL, or camera-capture path is accepted.
NFR-5 — Bounded study-help knowledge (explicit)
Study help must be limited to the built-in knowledge topics matematika, bahasa, ipa, ips, plus a default answer. Rationale: the source defines exactly this knowledge base and no retrieval or generation beyond it.
NFR-6 — Single-frame video reading (explicit) Video reading must process a single frame from the file. Rationale: the source reads one frame and releases the video; multi-frame scanning is not accepted.
NFR-7 — Local microphone access (required_inference) The application must be able to open the local microphone and adjust for ambient noise for 0.5 seconds before listening. Rationale: the accepted voice journey cannot execute without microphone capture.
NFR-8 — Text-to-speech availability (required_inference) A text-to-speech engine must be available and configured with rate 175 and volume 1.0. Rationale: every accepted capability produces a spoken result.
NFR-9 — Readable text and controls at every viewport (required_inference) Headlines, wordmarks, labels, numbers, card text and controls must remain entirely inside the viewport and their container at 375px, 768px and 1280px, wrapping or scaling to fit, with no other element covering any part of them. Rationale: the creative direction requires this and the product is read aloud and read slowly.
NFR-10 — Reduced-motion support (required_inference)
Under prefers-reduced-motion, the breathing ring must freeze into a static filled circle with a text state label and all motion must stop while the layout stays usable. Rationale: the creative direction specifies this reduced-motion state.
NFR-11 — Warm-tinted, low-opacity shadows (required_inference)
Shadows must be wide, low-opacity and warm-tinted (rgba(64,48,32,0.08), 24px blur) so panels feel like objects resting on cloth. Rationale: the creative direction specifies this surface treatment.
Source-specified technologies are preserved exactly:
speech_recognition — microphone capture and Indonesian speech recognition via recognize_google with language="id-ID".pyttsx3 — text-to-speech, initialized with rate 175 and volume 1.0.opencv-python (cv2) — video file opening and single-frame extraction, with BGR→RGB conversion.pytesseract — OCR with lang='ind'.Pillow (PIL.Image) — image opening and conversion from the extracted video frame.numpy — array support for frame handling.time and sys — imported by the source implementation.Supporting defaults [Default — not specified by user]:
[Default — not specified by user][Default — not specified by user][Default — not specified by user][Default — not specified by user][Default — not specified by user]Assumptions.
Constraints.
id-ID). (explicit)lang='ind'). (explicit)matematika, bahasa, ipa, ips, plus a default answer. (explicit)#FFFFFF grounds. (explicit)prefers-reduced-motion.tidak terdengar — the internal result returned when speech is not recognized; it triggers the spoken retry message.koneksi bermasalah — the internal result returned when the recognition service cannot be reached; it triggers the spoken retry message.id-ID — the Indonesian language code used for speech recognition.ind — the Indonesian language data identifier used for OCR.matematika, bahasa, ipa, ips, plus a default answer.
Emoto AI
Teman belajar bersuara untuk Alfian — mendengar pertanyaanmu, menjawab dengan tenang, dan membacakan teks dari foto maupun video.
Emoto berbicara“Halo! Aku Emoto, teman pintarmu! Siap membantu kapan saja!”
Kalau mesin suara atau mikrofon belum tersedia, Alfian tetap bisa membuka menu utama dan memakai kemampuan tanpa suara: membaca teks dari foto, membaca teks dari file video, dan minta bantuan belajar.

Emoto AI
Teman belajar bersuara untuk Alfian — mendengar pertanyaanmu, menjawab dengan tenang, dan membacakan teks dari foto maupun video.
Emoto berbicara“Halo! Aku Emoto, teman pintarmu! Siap membantu kapan saja!”
Kalau mesin suara atau mikrofon belum tersedia, Alfian tetap bisa membuka menu utama dan memakai kemampuan tanpa suara: membaca teks dari foto, membaca teks dari file video, dan minta bantuan belajar.
No comments yet. Be the first!