fichier.class.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. <?php
  2. class fichier
  3. {
  4. static public function add(array $file, array $form)
  5. {
  6. if ($file['error'] === UPLOAD_ERR_OK && !empty($file["tmp_name"])) {
  7. $md5 = md5_file($file["tmp_name"]);
  8. $hash = self::generateHash($file['name']);
  9. $durationInSeconds = fichier::getVideoDuration($file["tmp_name"]);
  10. if (copy($file["tmp_name"], ROOT_DIR . "/video/" . $md5 . ".mp4")) {
  11. db::query("INSERT INTO videos (title, titleTmp, type, size, duration, md5, hash, active, dateEvent, user) VALUES (:title, :titleTmp, :type, :size, :duration, :md5, :hash, :active, :dateEvent, :user)");
  12. db::bind(':title', htmlspecialchars($form['videoName']));
  13. db::bind(':titleTmp', htmlspecialchars($file['name']));
  14. db::bind(':type', htmlspecialchars($file['type']));
  15. db::bind(':size', (int)$file['size']);
  16. db::bind(':duration', $durationInSeconds);
  17. db::bind(':md5', $md5);
  18. db::bind(':hash', $hash);
  19. db::bind(':active', (int)$form['videoStatus']);
  20. db::bind(':dateEvent', $form["dateEvent"]);
  21. db::bind(':user', htmlspecialchars($_SESSION["USER"]["name"]));
  22. try {
  23. db::execute();
  24. alert::addAlert('success', 'Vidéo ajoutée avec succès.');
  25. return $hash;
  26. } catch (Exception $ex) {
  27. error_log($ex->getMessage()); // Log l'erreur pour un examen ultérieur
  28. alert::addAlert('error', 'Erreur lors de l\'ajout de la vidéo : ' . $ex->getMessage());
  29. return FALSE;
  30. }
  31. }
  32. }
  33. alert::addAlert('error', 'Erreur lors de l\'upload de la vidéo.');
  34. return FALSE;
  35. }
  36. static public function update(array $form)
  37. {
  38. db::query(" UPDATE videos SET
  39. title = :title,
  40. dateEvent = :dateEvent,
  41. active = :active
  42. WHERE id = :id");
  43. db::bind(':title', $form["videoName"]);
  44. db::bind(':dateEvent', $form["dateEvent"]);
  45. db::bind(':active', $form["videoStatus"]);
  46. db::bind(':id', $form["id"]);
  47. db::execute();
  48. alert::addAlert('success', 'Vidéo mise à jour avec succès.');
  49. }
  50. static public function updateTime($_id, $_duration)
  51. {
  52. db::query(" UPDATE videos SET
  53. duration = :duration
  54. WHERE id = :id");
  55. db::bind(':duration', $_duration);
  56. db::bind(':id', $_id);
  57. db::execute();
  58. }
  59. public static function delete(string $_md5, string $_folderFiles = ROOT_DIR . "/video/")
  60. {
  61. if (isset($_md5) and $_md5 != NULL and file_exists($_folderFiles . $_md5 . ".mp4")) {
  62. if (unlink($_folderFiles . $_md5 . ".mp4")) {
  63. unlink($_folderFiles . $_md5 . ".jpg");
  64. db::query("DELETE FROM videos WHERE md5 = :md5");
  65. db::bind(':md5', $_md5);
  66. try {
  67. db::execute();
  68. alert::addAlert('success', 'Vidéo supprimée avec succès.');
  69. return TRUE;
  70. } catch (Exception $ex) {
  71. alert::addAlert('error', 'Erreur lors de la suppression de la vidéo en base de données.');
  72. return FALSE;
  73. }
  74. } else {
  75. alert::addAlert('error', 'Erreur lors de la suppression du fichier vidéo.');
  76. return FALSE;
  77. }
  78. } else {
  79. alert::addAlert('error', 'Fichier vidéo introuvable.');
  80. return FALSE;
  81. }
  82. }
  83. static public function getById(float $id)
  84. {
  85. db::query("SELECT "
  86. . "*"
  87. . "FROM videos "
  88. . "WHERE id = :id");
  89. db::bind(':id', $id);
  90. try {
  91. $return = db::single();
  92. return $return;
  93. } catch (Exception $ex) {
  94. return FALSE;
  95. }
  96. }
  97. static public function getByHash(string $hash)
  98. {
  99. db::query("SELECT "
  100. . "*"
  101. . "FROM videos "
  102. . "WHERE hash = :hash");
  103. db::bind(':hash', $hash);
  104. try {
  105. $return = db::single();
  106. return $return;
  107. } catch (Exception $ex) {
  108. return FALSE;
  109. }
  110. }
  111. static public function getAll()
  112. {
  113. db::query("SELECT "
  114. . "*"
  115. . "FROM videos ORDER BY id DESC");
  116. try {
  117. $return = db::resultset();
  118. return $return;
  119. } catch (Exception $ex) {
  120. return FALSE;
  121. }
  122. }
  123. static private function generateHash($string)
  124. {
  125. $timestamp = time();
  126. $combined = $string . $timestamp;
  127. $hashValue = hash('sha256', $combined);
  128. return $hashValue;
  129. }
  130. static public function getVideoDuration($filePath)
  131. {
  132. $command = "ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 " . escapeshellarg($filePath);
  133. $duration = shell_exec($command);
  134. if ($duration) {
  135. return trim($duration);
  136. } else {
  137. return NULL;
  138. }
  139. }
  140. static public function generatePreview($_md5)
  141. {
  142. $videoPreview = ROOT_DIR . "/video/" . $_md5 . ".jpg";
  143. if (file_exists($videoPreview)) {
  144. return ['success' => TRUE, 'file' => 'Le fichier existe déjà'];
  145. }
  146. $time = "00:00:00";
  147. $videoFile = ROOT_DIR . "/video/" . $_md5 . ".mp4";
  148. if (!file_exists($videoFile)) {
  149. return ['success' => FALSE, 'error' => 'Le fichier vidéo n\'existe pas.'];
  150. }
  151. // Générer un nom unique pour le fichier de sortie
  152. $outputFile = tempnam(sys_get_temp_dir(), 'preview_') . '.jpg';
  153. // Commande FFmpeg pour faire une capture d'image
  154. $command = "ffmpeg -i " . escapeshellarg($videoFile)
  155. . " -frames:v 1 -q:v 5 " . escapeshellarg($outputFile);
  156. // Exécuter la commande FFmpeg
  157. exec($command, $output, $return_var);
  158. // Vérifier si la commande a réussi
  159. if ($return_var === 0) {
  160. $destinationFile = ROOT_DIR . "/video/" . $_md5 . ".jpg";
  161. if (copy($outputFile, $destinationFile)) {
  162. unlink($outputFile); // Supprimer le fichier temporaire
  163. return ['success' => TRUE, 'file' => $destinationFile];
  164. } else {
  165. unlink($outputFile); // Supprimer le fichier temporaire en cas d'échec
  166. return ['success' => FALSE, 'error' => 'Erreur lors de la copie du fichier généré.'];
  167. }
  168. } else {
  169. unlink($outputFile); // Supprimer le fichier temporaire en cas d'échec
  170. return ['success' => FALSE, 'error' => 'Erreur lors de l\'exécution de la commande FFmpeg.'];
  171. }
  172. }
  173. static public function cut()
  174. {
  175. if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  176. // Validation basique des temps de début et de fin
  177. $startTime = $_POST['startTime'];
  178. $endTime = $_POST['endTime'];
  179. // Vérifier que les temps sont au bon format (HH:MM:SS)
  180. if (!preg_match('/^\d{2}:\d{2}:\d{2}$/', $startTime) || !preg_match('/^\d{2}:\d{2}:\d{2}$/', $endTime)) {
  181. alert::addAlert('error', 'Format incorrect pour startTime ou endTime.');
  182. return ['success' => FALSE, 'error' => 'Format incorrect pour startTime ou endTime.'];
  183. }
  184. // Chemin sécurisé du fichier vidéo
  185. $videoFile = ROOT_DIR . "/video/" . basename($_POST['md5']) . ".mp4";
  186. if (!file_exists($videoFile)) {
  187. alert::addAlert('error', 'Le fichier vidéo n\'existe pas.');
  188. return ['success' => FALSE, 'error' => 'Le fichier vidéo n\'existe pas.'];
  189. }
  190. // Générer un nom unique pour le fichier de sortie
  191. $outputFile = tempnam(sys_get_temp_dir(), 'cut_') . '.mp4';
  192. // Commande FFmpeg pour découper la vidéo
  193. $command = "ffmpeg -i " . escapeshellarg($videoFile)
  194. . " -ss " . escapeshellarg($startTime)
  195. . " -to " . escapeshellarg($endTime)
  196. . " -force_key_frames 'expr:gte(t,n_forced*1)' -c copy -movflags +faststart "
  197. . escapeshellarg($outputFile);
  198. // Exécuter la commande FFmpeg
  199. exec($command, $output, $return_var);
  200. // Vérifier si la commande a réussi
  201. if ($return_var === 0) {
  202. $destinationFile = ROOT_DIR . "/video/_" . basename($_POST['md5'] . ".mp4");
  203. if (copy($outputFile, $destinationFile)) {
  204. unlink($outputFile); // Supprimer le fichier temporaire
  205. alert::addAlert('success', 'Vidéo découpée avec succès.');
  206. return ['success' => TRUE, 'file' => $destinationFile];
  207. } else {
  208. unlink($outputFile); // Supprimer le fichier temporaire en cas d'échec
  209. alert::addAlert('error', 'Erreur lors de la copie du fichier généré.');
  210. return ['success' => FALSE, 'error' => 'Erreur lors de la copie du fichier généré.'];
  211. }
  212. } else {
  213. unlink($outputFile); // Supprimer le fichier temporaire en cas d'échec
  214. alert::addAlert('error', 'Erreur lors de l\'exécution de la commande FFmpeg.');
  215. return ['success' => FALSE, 'error' => 'Erreur lors de l\'exécution de la commande FFmpeg.'];
  216. }
  217. } else {
  218. alert::addAlert('error', 'Requête non autorisée.');
  219. return ['success' => FALSE, 'error' => 'Requête non autorisée.'];
  220. }
  221. }
  222. static public function iniSizeToBytes($upload_max_filesize = null)
  223. {
  224. $upload_max_filesize = $upload_max_filesize ?? ini_get('upload_max_filesize');
  225. $val = trim($upload_max_filesize);
  226. // Parse a numeric value and an optional unit (K, M, G) with optional trailing "B"
  227. if (preg_match('/^(\d+(?:\.\d+)?)\s*([kKmMgG])?(?:b|B)?$/', $val, $matches)) {
  228. $num = (float)$matches[1];
  229. $unit = isset($matches[2]) ? strtolower($matches[2]) : '';
  230. // Fall-through intentional to multiply by 1024 per unit level
  231. switch ($unit) {
  232. case 'g':
  233. $num *= 1024;
  234. case 'm':
  235. $num *= 1024;
  236. case 'k':
  237. $num *= 1024;
  238. }
  239. return (int)$num;
  240. }
  241. return (int)(float)$val;
  242. }
  243. static public function bytesToHuman($size = null)
  244. {
  245. // Récupère la valeur si non fournie
  246. $val = $size ?? ini_get('post_max_size');
  247. $val = trim($val);
  248. $last = strtolower($val[strlen($val) - 1]);
  249. $num = (float)$val;
  250. // Convertit les suffixes en octets (fall-through voulu)
  251. switch ($last) {
  252. case 'g':
  253. $num *= 1024;
  254. case 'm':
  255. $num *= 1024;
  256. case 'k':
  257. $num *= 1024;
  258. }
  259. $bytes = (float)$num;
  260. $units = ['B', 'KB', 'MB', 'GB', 'TB'];
  261. $i = 0;
  262. while ($bytes >= 1024 && $i < count($units) - 1) {
  263. $bytes /= 1024;
  264. $i++;
  265. }
  266. return round($bytes, ($bytes >= 100 ? 0 : 1)) . ' ' . $units[$i];
  267. }
  268. }