Library
🎬 Video B1 Easy Cantonese 3 — What Do You Like About Hong Kong?
Easy Cantonese 3 — What Do You Like About Hong Kong?
你最鍾意香港咩?
About this video Easy Languages asks Hong Kong locals what they love most about their city. Natural street Cantonese with varied vocabulary — great for B1 learners building conversational confidence.
Transcript
00:00
zyu2 ci4 jan4: nei5 hou2! nei5 zeoi3 zung1 ji3 hoeng1 gong2 me1?
Host: Hello! What do you like most about Hong Kong?
00:16
hoeng1 gong2 ge3 jam2 sik6 man4 faa3 hai6 cyun4 sai3 gaai3 zeoi3 hou2 ge3, hou2 do1 syun2 zaak3.
Hong Kong's food culture is the best in the world — so many choices.
00:30
便
ngo5 zeoi3 zung1 ji3 hai6 hoeng1 gong2 hou2 fong1 bin6, heoi3 bin1 dou6 dou1 hai6 sap6 gei2 fan1 zung1.
What I like most is how convenient Hong Kong is. Everywhere is just ten-plus minutes away.
00:46
je6 maan5 ge3 wai4 do1 lei6 aa3 gong2 ging2 sik1 zan1 hai6 hou2 leng3, ngo5 hou2 zung1 ji3.
The Victoria Harbour night view is really beautiful. I love it.
01:02
hoeng1 gong2 jan4 hou2 jit6 cing4, jau6 kan4 lik6, ni1 go3 hai6 ngo5 zeoi3 jan1 soeng2 ge3 dei6 fong1.
Hong Kong people are very warm and hardworking. That is what I admire most.
01:18
ngo5 zeoi3 zung1 ji3 hai6 ni1 dou6 ge3 gaau1 tung1, dei6 tit3 sei3 tung1 baat3 daat6, jau6 faai3 jau6 zeon2 si4.
What I love most is the transport here. The MTR goes everywhere and is fast and punctual.
01:34
西
ni1 dou6 ge3 man4 faa3 hou2 do1 jyun4, jau5 zung1 jau5 sai1, hai6 jat1 go3 hou2 duk6 dak6 ge3 sing4 si5.
The culture here is very diverse, Chinese and Western. It is a very unique city.
01:52
do1 ze6 nei5 fan1 hoeng2! hoeng1 gong2 zan1 hai6 hai6 jat1 go3 hou2 dak6 bit6 ge3 dei6 fong1.
Thank you for sharing! Hong Kong really is a very special place.
/** * Cantonese.hk — Audio Helper * Uses POST to /api/audio.php to bypass Cloudflare CDN cache. * Converts response to Blob URL for playback. * * Exposes: * window.cantoAudio — the shared Audio element (set once created) * window.cantoSpeak(text, btn, rate) * window.cantoSpeakWord(wordId, fallbackText, btn) * window.cantoStop() * * Dispatches on document: * 'cantoplaystart' — when audio.play() is called ({ detail: { text } }) * 'cantoplayend' — when audio ends or errors */ (function() { 'use strict'; var audioEl = null; var currentBtn = null; var currentBlob = null; function getAudio() { if (!audioEl) { audioEl = new Audio(); window.cantoAudio = audioEl; // expose for external karaoke hooks } return audioEl; } function revokeBlob() { if (currentBlob) { URL.revokeObjectURL(currentBlob); currentBlob = null; } } function clearPlaying() { if (currentBtn) { currentBtn.classList.remove('playing'); currentBtn = null; } } function dispatchEnd() { document.dispatchEvent(new CustomEvent('cantoplayend')); } window.cantoStop = function() { clearPlaying(); if (audioEl) { audioEl.pause(); audioEl.src = ''; } revokeBlob(); if ('speechSynthesis' in window) window.speechSynthesis.cancel(); dispatchEnd(); }; // POST text to audio.php, play response as blob window.cantoSpeak = function(text, btn, rate) { if (!text) return; clearPlaying(); if (audioEl) { audioEl.pause(); audioEl.src = ''; } revokeBlob(); if ('speechSynthesis' in window) window.speechSynthesis.cancel(); if (btn) { currentBtn = btn; btn.classList.add('playing'); } var fd = new FormData(); fd.append('action', 'speak'); fd.append('text', text); fetch('/api/audio.php', {method: 'POST', body: fd}) .then(function(r) { if (r.status === 204 || !r.ok) throw new Error('no audio'); return r.blob(); }) .then(function(blob) { var url = URL.createObjectURL(blob); currentBlob = url; var audio = getAudio(); audio.onended = function() { clearPlaying(); revokeBlob(); dispatchEnd(); }; audio.onerror = function() { clearPlaying(); revokeBlob(); dispatchEnd(); }; audio.src = url; // Fire cantoplaystart so readers can attach timeupdate karaoke document.dispatchEvent(new CustomEvent('cantoplaystart', { detail: { text: text, audio: audio } })); return audio.play(); }) .catch(function() { fallbackWebSpeech(text, rate); }); }; function fallbackWebSpeech(text, rate) { if (!('speechSynthesis' in window)) { clearPlaying(); return; } var u = new SpeechSynthesisUtterance(text); u.lang = 'zh-HK'; u.rate = rate || 0.8; var voices = window.speechSynthesis.getVoices(); for (var i = 0; i < voices.length; i++) { var vl = voices[i].lang.toLowerCase(); if (vl === 'zh-hk' || vl === 'yue-hk' || vl.indexOf('yue') !== -1 || vl === 'zh-tw') { u.voice = voices[i]; break; } } u.onend = function() { clearPlaying(); dispatchEnd(); }; u.onerror = function() { clearPlaying(); dispatchEnd(); }; window.speechSynthesis.speak(u); } if ('speechSynthesis' in window) { window.speechSynthesis.getVoices(); window.speechSynthesis.onvoiceschanged = function() { window.speechSynthesis.getVoices(); }; } window.cantoSpeakWord = function(wordId, fallbackText, btn) { if (!wordId) { cantoSpeak(fallbackText, btn); return; } var xhr = new XMLHttpRequest(); xhr.open('GET', '/api/audio.php?action=word&id=' + encodeURIComponent(wordId), true); xhr.timeout = 2000; xhr.onload = function() { if (xhr.status === 200) { try { var data = JSON.parse(xhr.responseText); cantoSpeak(data.text || fallbackText, btn); } catch(e) { cantoSpeak(fallbackText, btn); } } else { cantoSpeak(fallbackText, btn); } }; xhr.onerror = function() { cantoSpeak(fallbackText, btn); }; xhr.ontimeout = function() { cantoSpeak(fallbackText, btn); }; xhr.send(); }; document.addEventListener('DOMContentLoaded', function() { document.addEventListener('click', function(e) { var btn = e.target.closest('.audio-play'); if (!btn) return; e.preventDefault(); e.stopPropagation(); if (typeof window.stopPlayAll === 'function') window.stopPlayAll(); var text = btn.getAttribute('data-text'); var wordId = btn.getAttribute('data-word-id'); if (wordId) { cantoSpeakWord(wordId, text, btn); } else if (text) { cantoSpeak(text, btn); } }); }); })();