Skip to content

MP4 valid yang nggak akan pernah tertranscribe

Adityo Guni Waluyo

File video bisa saja valid tapi tak punya audio. Aksi skip nonstate membuat barisnya tetap kelihatan dan menahan pipeline sampai ada keputusan.

Ringkasan

File MP4-nya valid, cuma isinya nggak ada track audio sama sekali, jadi asumsi video pasti punya suara itu salah. Sekarang ffprobe dicek duluan sebelum ekstraksi, hasil flag audio_track disimpan di meta.json, dan kalau nggak ada audio barisnya di-skip tapi tetap keliatan, bukan ditandai selesai. Frame video diekstrak pakai fps konstan plus timestamp, audionya jadi WAV mono 16kHz.

Ada momen yang rasanya kayak nemu file rusak: satu berkas MP4 masuk jalur ingest, player memutarnya dengan normal, tapi begitu nyampe di antrean transkripsi nggak ada apa pun yang bisa diproses. Tebakan pertama saya: kontainernya corrupt, atau setidaknya setengah rusak.

Ternyata jauh lebih sederhana. Berkas itu valid. Kontainernya utuh; isinya memang nggak punya audio sama sekali. Nol stream audio. Yang salah bukan file-nya, tapi asumsi saya bahwa video "pasti" bawa jalur suara.

Kontainer valid, audio nol

Kabar baiknya, pertanyaan "apakah berkas ini punya audio" nggak perlu dijawab pakai coba-dan-gagal. ffprobe punya -show_streams yang mencetak satu bagian STREAM untuk tiap media stream, dan -select_streams a menyaring hasilnya cuma ke audio [1]. Output kosong berarti jawabannya kosong.

Di pipeline ingest saya, ekstensi .mp4, .mov, dan .mkv sekarang ikut masuk jalur media. Job media menjalankan ffprobe lebih dulu, lalu menyimpan flag audio_track berisi true atau false di meta.json, di samping daftar frame yang diekstrak.

Urutannya juga nggak kebalik. ffprobe dijalankan sebelum ekstraksi, supaya pertanyaan termurah terjawab lebih dulu: membaca metadata itu murah, men-decode isi video mahal. Versi ffprobe-nya pun ikut disimpan di meta, jadi kalau perilakunya berubah antar versi, jejaknya masih bisa dilacak.

Skip yang nggak bohong

Begitu audio_track false, planner memunculkan aksi skip-no-audio. Saya sengaja bikin aksi ini NONSTATE: nggak ada status "done" yang ditulis, aksi yang sama muncul lagi di setiap run planner, dan barisnya tetap berstatus media-extracted yang memblokir penutupan pipeline. Skip yang menulis done itu bohong. Saya lebih percaya skip yang bikin baris tetap kelihatan, supaya file bermasalah nggak lolos diam-diam sebagai pekerjaan selesai.

Tetap ada lapis kedua. Kalau ada plan lama yang nekat menyuruh worker mentranskripsi video tanpa audio, worker mati dengan exit 1 dan alasan no-audio-track. Dua penjaga untuk satu kondisi, dan menurut saya porsi itu pas.

Kadence frame yang bisa dihitung

Sisi videonya sendiri saya perlakukan sebagai kontrak, bukan kebetulan. Filter fps mengubah video ke frame rate konstan dengan menduplikasi atau membuang frame, jadi fps=1/interval menghasilkan tepat satu frame tiap interval detik [3]. Opsi frame_pts=1 di muxer image2 bikin nama file memakai timestamp paket: f0000 ada di t=0, dan file ke-i di urutan sorted ada di t = i kali interval [4]. Angkanya mencerminkan waktu, bukan urutan ekstraksi.

Ekstraksi ulang menghapus frame lama lebih dulu, supaya interval yang berubah nggak mencampur dua kadence dalam satu direktori.

Ekstraksinya juga dibatasi. Opsi -frames:v N berhenti menulis ke stream setelah N frame [2], jadi frame ekstra nggak pernah didekode; mereka cuma dicatat sebagai entri bertimestamp dengan flag deferred. Untuk audionya, jalurnya nyaris sama kayak audio biasa: -vn sebagai opsi input memblokir semua video stream dari output, ffmpeg cuma mendekode audio, lalu diturunkan jadi WAV mono 16 kHz untuk whisper [2].

Resource buat mendekode video yang nggak akan menghasilkan teks itu mubazir. Yang lebih penting, keputusannya harus kebaca: berkas kayak ini nggak gagal dan nggak selesai. Dia di-skip dengan jejak yang tetap tergantung di plan, sampai ada yang memutuskan nasibnya.

Sumber

  1. ffprobe Documentation
  2. FFmpeg Documentation
  3. FFmpeg Filters Documentation
  4. FFmpeg Formats Documentation

Artikel terkait