exec("ffmpeg -i ...") 轉碼為 FLV。<?php
$file = 'video_file'; // input name
$config['upload_path'] = './video_folder/';
$config['allowed_types'] = 'mov|mpeg|mp3|avi';
$config['max_size'] = '50000'; // KB
$config['max_width'] = '';
$config['max_height'] = '';
$this->load->library('upload', $config);
if (!$this->upload->do_upload($file)) {
$err_msgs .= '上傳失敗:' . $this->upload->display_errors() . '<br>';
} else {
$data = $this->upload->data();
$video_path = $data['file_name'];
$directory_path = $data['file_path'];
$full_path = $data['full_path'];
$raw_name = $data['raw_name']; // 不含副檔名
// ffmpeg 轉檔:同目錄輸出 .flv
$cmd = "ffmpeg -i " . escapeshellarg($full_path) . " " . escapeshellarg($directory_path . $raw_name . ".flv");
exec($cmd, $output, $return_var);
if ($return_var !== 0) {
log_message('error', "ffmpeg 失敗: " . implode("\n", $output));
show_error('影片轉檔失敗');
}
// 寫入資料庫
$this->db->set('video', $raw_name . '.flv');
$this->db->where('id', $id);
$this->db->update('user_videos');
}
?>
escapeshellarg() 必加防止檔名含空格、分號、反引號等導致命令注入。
$ffmpeg = '/usr/bin/ffmpeg'; // 明確指定路徑
$cmd = "{$ffmpeg} -y -i " . escapeshellarg($full_path) .
" -c:v libx264 -preset fast -crf 23 -c:a aac -b:a 128k " .
escapeshellarg($directory_path . $raw_name . ".flv");
-y:覆蓋輸出檔不詢問。-preset fast -crf 23:速度/品質平衡預設值。轉檔耗時秒~分級,不可阻塞 HTTP 請求。建議:
// 上傳後再次驗證 MIME
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($full_path);
if (!in_array($mime, ['video/quicktime', 'video/mpeg', 'video/mp4', 'video/x-msvideo'])) {
unlink($full_path);
show_error('檔案類型不符');
}
CREATE TABLE user_videos (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
video VARCHAR(255) NOT NULL, // 儲存 xxx.flv
original_name VARCHAR(255),
status ENUM('pending','processing','ready','failed') DEFAULT 'pending',
duration INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);