Skip to content

Video Altyazıları (Bunny Stream)

Uçtan uca altyazı sistemi — veritabanı, Bunny Stream API, eğitmen yükleme/silme, öğrenci oynatıcıda gösterim.

Achidemy’de ders videolarına altyazı (.vtt) ekleme, Bunny.net Stream API ile senkron çalışır. Eğitmen altyazı yükler; sistem hem Bunny’e hem veritabanına kaydeder. Öğrenci tarafında video oynatıcıda altyazılar otomatik listelenir ve varsayılan dil iframe parametresi ile açılabilir.

  1. Eğitmen: Müfredat veya “Altyazılar” sayfasından ders seçer → dil seçer → .vtt dosyası yükler → POST /api/lesson/caption-upload.
  2. Backend: Dersin bunnyVideoId’si ile Bunny Stream “Add Caption” API’ye istek atar; başarılıysa lesson_captions tablosuna kayıt ekler.
  3. Öğrenci: learn/:slug sayfasında video yüklenirken loader ders altyazılarını çeker; iframe URL’ine ?captions=tr (veya seçilen dil) eklenir. Bunny oynatıcı CC menüsünde altyazıları gösterir.
  4. Silme: Eğitmen altyazı silerse POST /api/lesson/caption-delete → önce Bunny’den silinir, sonra veritabanından.

Dosya: app/db/schema.ts

SütunTipAçıklama
iduuidPK, default random.
lesson_iduuidFK → lessons.id, on delete cascade.
language_codetextDil kodu (örn. tr, en, de).
labeltextGörünen etiket (örn. Türkçe, English).
bunny_urltextOpsiyonel; Bunny tarafındaki dosya yolu.
created_attimestampKayıt zamanı.

Altyazı listesi öğrenci sayfasında loader’da lesson_captions tablosundan ders bazlı çekilir; iframe’e varsayılan dil parametresi verilir.

Kurs Seviyesi: Desteklenen Altyazı Dilleri (subtitle_languages)

Section titled “Kurs Seviyesi: Desteklenen Altyazı Dilleri (subtitle_languages)”

Kurs başlığı altında “Bu kursta hangi dillerde altyazı var?” bilgisi kurs bazlı saklanır ve gösterilir.

Veritabanı: courses.subtitle_languages (text[]). Eğitmen landing veya kurs yönetiminde desteklenen altyazı dillerini seçer (örn. tr, en, de); bu kodlar dizi olarak kaydedilir.

Kurs sayfası (course.$id): Hero bölümünde ilk birkaç dil adı (Türkçe, English, Deutsch vb.) ve ”+ N daha” metni gösterilir. ”+ N daha” veya “(Tümünü gör)” tıklanınca bir modal açılır; tüm desteklenen diller “[Otomatik]” etiketiyle listelenir. Dil adları app/routes/course.$id.tsx içindeki langNames eşlemesiyle (tr → Türkçe, en → English, de → Deutsch, vb.) gösterilir.

Eğitmen tarafı: Landing sayfasında veya kurs yönetiminde altyazı dilleri çoklu seçim ile güncellenir; GraphQL updateCourse(subtitleLanguages) veya ilgili form ile courses.subtitle_languages yazılır.

Bu özellik, ders bazlı .vtt altyazılarından (lesson_captions) bağımsızdır: ders altyazıları hangi dillerde yüklü, kurs meta verisi ise “bu kurs şu dillerde altyazı sunuyor” listesidir.

Dosya: app/lib/bunny.ts

  • Ortam değişkenleri: BUNNY_LIBRARY_ID, BUNNY_STREAM_API_KEY (veya BUNNY_API_KEY — kodda fallback). Cloudflare Workers’ta API key güvenli şekilde env üzerinden okunur.
  • uploadCaptionToBunny(videoId, langCode, label, fileBuffer, env):
    POST https://video.bunnycdn.com/library/{libraryId}/videos/{videoId}/captions/{srclang}
    Body: { srclang, label, captionsFile }captionsFile base64 ile gönderilir. Workers’ta Buffer yok; base64 Web API (btoa + Uint8Array) ile üretilir.
  • getBunnyCaptions(videoId, env): Video detayından captions dizisini döndürür.
  • deleteBunnyCaption(videoId, langCode, env): DELETE .../videos/{videoId}/captions/{langCode}.

Bunny dokümantasyonu: Add Caption — path captions (çoğul), body alanı captionsFile.

Bunny CDN geliştirmeleri ve daha fazla bilgi için: Bunny.net Dokümantasyonu

EndpointMethodDosyaAçıklama
POST /api/lesson/caption-uploadPOSTapi.lesson.caption-upload.tsAltyazı .vtt yükleme. FormData: lessonId, captionFile, langCode, label. Bunny’e gönderir; başarılıysa lesson_captions’a insert.
POST /api/lesson/caption-deletePOSTapi.lesson.caption-delete.tsAltyazı silme. FormData: captionId. Önce Bunny’den siler, sonra DB’den.

Her iki endpoint de 500 hatalarında JSON döner ({ "error": "..." }); React fetcher’ın HTML hata sayfası alması engellenir.

  • Müfredat sayfası: app/routes/instructor.course.$slug.manage.curriculum.tsx
    Videolu her ders için “Altyazılar” butonu (CaptionManager). Tıklanınca modal açılır; dil seçimi + .vtt dosyası + “Bunny.net’e Gönder” ile caption-upload çağrılır.
  • Altyazılar sayfası: app/routes/instructor.course.$slug.manage.captions.tsx
    URL: /:lang/instructor/course/:slug/manage/captions. Bölüm/ders listesi; videolu derslerde mevcut altyazılar listelenir, “Altyazı Ekle” ve satır bazlı “Sil” (caption-delete) kullanılır.
  • Route: routes.ts içinde course/:slug/manage altında captionsinstructor.course.$slug.manage.captions.tsx.
  • Loader: Müfredat çekilirken her ders için lesson_captions tablosundan id, languageCode, label alınır; derse captions dizisi eklenir.
  • Video URL: Varsayılan altyazı dili (önce tr, yoksa ilk dil) seçilir; iframe URL’ine ?captions=tr (veya ilgili kod) eklenir. Bunny embed bu parametre ile varsayılan altyazıyı açar.
  • Erişilebilirlik: Altyazı varsa ekranda görünmeyen (sr-only) metin ile “Altyazılar: Türkçe, English” benzeri bilgi verilir.
DeğişkenAçıklama
BUNNY_LIBRARY_IDBunny Stream kütüphane ID’si (altyazı endpoint path’inde kullanılır).
BUNNY_API_KEY veya BUNNY_STREAM_API_KEYBunny Stream API anahtarı. .dev.vars / .env içinde BUNNY_API_KEY kullanılıyorsa kod bunu otomatik okur.

Yerelde .dev.vars (Wrangler) veya .env (process.env) ile birleştirilerek okunur; Cloudflare Workers’ta context.cloudflare.env önceliklidir.

DosyaGörev
app/db/schema.tslessonCaptions tablosu.
app/lib/bunny.tsuploadCaptionToBunny, getBunnyCaptions, deleteBunnyCaption; Workers uyumlu base64.
app/routes/api.lesson.caption-upload.tsAltyazı yükleme action; env birleştirme, try/catch, JSON 500.
app/routes/api.lesson.caption-delete.tsAltyazı silme action.
app/routes/learn.$slug.tsxLoader’da captions, videoUrl’de captions param, sr-only altyazı listesi.
app/routes/instructor.course.$slug.manage.curriculum.tsxCaptionManager bileşeni, “Altyazılar” butonu.
app/routes/instructor.course.$slug.manage.captions.tsxAltyazılar yönetim sayfası (liste, ekle, sil).
app/routes.tsapi/lesson/caption-upload, api/lesson/caption-delete, manage/captions route’ları.
  • Veritabanı: lesson_captions — ders bazlı dil kodu ve etiket; Bunny’e dosya yolu opsiyonel.
  • Bunny: Stream “Add Caption” / “Delete Caption” API’leri; path captions (çoğul), body captionsFile (base64).
  • API: caption-upload (yükleme + DB insert), caption-delete (Bunny + DB delete); her zaman JSON yanıt.
  • Eğitmen: Müfredat’ta “Altyazılar” butonu + modal; ayrı “Altyazılar” sayfası (captions) ile liste/ekle/sil.
  • Öğrenci: Learn sayfasında loader ile altyazılar yüklenir; iframe’e ?captions= ile varsayılan dil verilir; Bunny oynatıcı CC menüsünde altyazıları gösterir.