Browse Source

add thumbnail generation and additional routes

Andrew 3 weeks ago
parent
commit
1bbd6316c3
3 changed files with 82 additions and 32 deletions
  1. 2 1
      .gitignore
  2. 68 27
      app/Controllers/VideoController.php
  3. 12 4
      app/Helpers.php

+ 2 - 1
.gitignore

@@ -2,4 +2,5 @@ usercontent/
 config.ini
 run.bat
 .vscode
-vendor/
+vendor/
+logs/

+ 68 - 27
app/Controllers/VideoController.php

@@ -3,6 +3,7 @@
 namespace app\Controllers;
 
 use app\Exceptions\AccountNotFoundException;
+use app\Exceptions\CommentNotFoundException;
 use app\Exceptions\VideoNotFoundException;
 use app\Hajeebtok;
 use Pecee\SimpleRouter\SimpleRouter;
@@ -11,36 +12,38 @@ use app\Interfaces\IRouteController;
 use app\Types\DatabaseObjects\Video;
 use app\Types\DatabaseObjects\Account;
 use app\Logger;
+use FFMpeg;
 
 class VideoController implements IRouteController
 {
 	public static function getVideo(string $id): string
 	{
-        $signedIn = signed_in(request());
+        $signed_in = signed_in(request());
 
-        $videoInformation = new Video($id);
-        $videoInformation->Load();
-        $mimeTypes = new MimeTypes();
+        $video_information = new Video($id);
+        $video_information->Load();
+        $mime_types = new MimeTypes();
 
-        if($signedIn) { // Signed in
-            $videoPath = APP_ROOT . "/usercontent/videos/$id/video.mp4";
+        if($signed_in) { // Signed in
+            $video_path = APP_ROOT . "/usercontent/videos/$id/video.mp4";
         } else { // not signed in
-            $videoPath = APP_ROOT . "/usercontent/videos/1/video.mp4";
+            $rand = rand(1, 48);
+            $video_path = APP_ROOT . "/usercontent/fake_videos/$rand/video.mp4";
         }
 
         CORSHelper();
-        if (file_exists($videoPath)) {
-            $videoContents = file_get_contents($videoPath);
-            $videoSize = filesize($videoPath);
+        if (file_exists($video_path)) {
+            $video_contents = file_get_contents($video_path);
+            $video_size = filesize($video_path);
 
-            $mime = $mimeTypes->getMimeType(pathinfo($videoPath, PATHINFO_EXTENSION));
+            $mime = $mime_types->getMimeType(pathinfo($video_path, PATHINFO_EXTENSION));
 
             $response = response();
             $response->header("Content-Type: $mime");
-            $response->header("Content-Length: $videoSize");
+            $response->header("Content-Length: $video_size");
             $response->header("Cache-Control: max-age=86400, public");
 
-            return $videoContents;
+            return $video_contents;
         } else {
             throw new VideoNotFoundException($id, 404);
         }
@@ -48,22 +51,22 @@ class VideoController implements IRouteController
 
 	public static function getInfo(string $id): string
 	{
-		$videoInformation = new Video($id);
-		$videoInformation->Load();
-		$authorInformation = new Account($videoInformation->author_id);
-		$authorInformation->Load();
+		$video_information = new Video($id);
+		$video_information->Load();
+		$author_information = new Account($video_information->author_id);
+		$author_information->Load();
 
 		return api_json([
-			"title" => $videoInformation->title,
-			"description" => $videoInformation->description,
-			"likes" => $videoInformation->likes,
-			"dislikes" => $videoInformation->dislikes,
-			"comments" => $videoInformation->comments,
-			"shares" => $videoInformation->shares,
+			"title" => $video_information->title,
+			"description" => $video_information->description,
+			"likes" => $video_information->likes,
+			"dislikes" => $video_information->dislikes,
+			"comments" => $video_information->comments,
+			"shares" => $video_information->shares,
 			"author" => [
-				"id" => $authorInformation->id,
-				"pictureHash" => $authorInformation->picture_hash,
-				"username" => $authorInformation->username
+				"id" => $author_information->id,
+				"pictureHash" => $author_information->picture_hash,
+				"username" => $author_information->username
 			],
 		]);
 	}
@@ -97,16 +100,54 @@ class VideoController implements IRouteController
         return api_json($data);
     }
 
+    public static function getThumbnail(string $id): string
+    {
+        $signed_in = signed_in(request());
+        $video_information = new Video($id);
+        $video_information->Load();
+
+        if($signed_in) { // Signed in
+            $seconds = 2;
+            $video_path = APP_ROOT . "/usercontent/videos/$id/video.mp4";
+            $frame_path = APP_ROOT . "/usercontent/videos/$id/thumbnail.png";
+        } else { // not signed in
+            $rand = rand(1, 47);
+            $seconds = 6;
+            $video_path = APP_ROOT . "/usercontent/fake_videos/$rand/video.mp4";
+            $frame_path = APP_ROOT . "/usercontent/fake_videos/$rand/thumbnail.png";
+        }
+
+        $mime_types = new MimeTypes();
+        if(!file_exists($video_path)) throw new VideoNotFoundException($id, 404);
+        if(!file_exists($frame_path)) {
+            $ffmpeg = FFMpeg\FFMpeg::create();
+            $video = $ffmpeg->open($video_path);
+            $frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds($seconds));
+            $frame->save($frame_path);
+        }
+
+        CORSHelper();
+        $mime = $mime_types->getMimeType(pathinfo($frame_path, PATHINFO_EXTENSION));
+        $response = response();
+        $response->header("Content-Type: $mime");
+        $response->header("Cache-Control: max-age=86400, public");
+
+        return file_get_contents($frame_path);
+    }
+
 	public static function RegisterRoutes(): void
 	{
 		SimpleRouter::group([
 			"prefix" => "/video",
 		], function () {
 			SimpleRouter::get("/{id}", [VideoController::class, "getVideo"]);
+            SimpleRouter::get("/{id}/info", [VideoController::class, "getInfo"]);
+            SimpleRouter::get("/{id}/thumbnail", [VideoController::class, "getThumbnail"]);
 			SimpleRouter::post("/upload", [VideoController::class, "uploadVideo"]);
-			SimpleRouter::get("/{id}/info", [VideoController::class, "getInfo"]);
             SimpleRouter::post("/search", [VideoController::class, "search"]);
             SimpleRouter::options("/{id}", "CORSHelper");
+            SimpleRouter::options("/{id}/info", "CORSHelper");
+            SimpleRouter::options("/{id}/thumbnail", "CORSHelper");
 		});
 	}
 }

+ 12 - 4
app/Helpers.php

@@ -101,8 +101,12 @@ function api_json(array $data): string
 
 function signed_in(Request $request): bool
 {
-    //$authorizationHeader = $request->getHeader("Authorization");
-    $authorizationHeader = urldecode($_COOKIE["token"]);
+    if(!empty($request->getHeader("Authorization"))) {
+        $authorizationHeader = $request->getHeader("Authorization");
+    } else {
+        $authorizationHeader = urldecode($_COOKIE["token"]);
+    }
+
     Logger::debug("Authorization header: $authorizationHeader");
     $token = explode(" ", $authorizationHeader)[1];
     $tokenData = Hajeebtok::$Database->Row("SELECT * FROM sessions WHERE token = :token", ["token" => $token]);
@@ -111,8 +115,12 @@ function signed_in(Request $request): bool
 
 function get_token_id(Request $request): int
 {
-    //$authorizationHeader = $request->getHeader("Authorization");
-    $authorizationHeader = urldecode($_COOKIE["token"]);
+    if(!empty($request->getHeader("Authorization"))) {
+        $authorizationHeader = $request->getHeader("Authorization");
+    } else {
+        $authorizationHeader = urldecode($_COOKIE["token"]);
+    }
+
     $token = explode(" ", $authorizationHeader)[1];
     $tokenData = Hajeebtok::$Database->Row("SELECT * FROM sessions WHERE token = :token", ["token" => $token]);
     if(!empty($tokenData)) return $tokenData["account_id"];