🐥
動画サイト的なもの作ってみた
動画サイト的なもの作ってみた
環境
- OS : Ubuntu 22.04
- WebServer : Apache 2.4.58
- CGI : PHP 8.2.12
- HTML : HTML Living Standard
0.設定
/etc/apache2/apache2.conf
/etc/apache2/apache2.conf
<Directory /var/www/>
Options Indexes FollowSymLinks
# AllowOverride None
AllowOverride All
Require all granted
</Directory>
.htaccess
AddType application/x-httpd-php .php .html
AddHandler application/x-httpd-php .php .html
php_value memory_limit 1000M
php_value post_max_size 1000M
php_value upload_max_filesize 1200M
1.HTML(UI)
とりあえず外側のHTMLを書いていきます。
index.html
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<link href="style.css" rel="stylesheet" />
<title>どーがさいと</title>
</head>
<body>
<h1>どーがさいと</h1>
<hr>
<div style="text-align: center;">
<h2>投稿</h2>
<form action="cgi-bin/videoPost.php" method="post" enctype="multipart/form-data">
動画タイトル (14文字まで): <input type="text" name="uploadTitle" maxlength="20"><br>
動画ファイル : <input type="file" name="upload_video"></br>
概要欄 (最大5行)</br>
<textarea name="uploadDescription" rows="8" cols="40" value="" maxlength="70"></textarea></br>
<input type="submit" value="投稿"></br>
</form>
<p>*Uploading may take some time for processing.</p>
<h2>動画リスト</h2>
</div>
<ul class="videoList">
<!-- ここに動画リスト -->
</ul>
</body>
</html>
watch.php
watch.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<link href="style.css" rel="stylesheet" />
<title>どーがさいと - <!-- 動画タイトル ここに設置 --></title>
</head>
<body>
<h1><!-- 動画タイトル ここに設置 --></h1>
<h3>概要欄</h3>
<!-- 概要欄 ここに設置 -->
<hr>
<!-- 動画 ここに設置 -->
<hr>
</body>
</html>
style.css
style.css
video{
width: 50%;
@media screen and (max-width: 480px) {
width: 100%;
}
}
pre{
white-space: pre-wrap;
font-size: x-large;
}
ul{
display: flex;
flex-wrap: wrap;
}
2.プログラム
cgi-binフォルダの中に書きます
cgi-bin/videoPost.php 動画投稿プログラム
cgi-bin/videoPost.php
<?php
function redirectBackPage(){
if (isset($_SERVER['HTTP_REFERER'])){
header("Location: ".$_SERVER['HTTP_REFERER']);
}
exit;
}
ob_start();
// getの引数がなかったりしたら前のページに戻る
if(!(!empty($_FILES) && isset($_POST["upload_title"]) && isset($_POST["upload_description"]))){redirectBackPage();}
// タイトルと概要欄の文字列を変数に代入する(htmlspecialcharsでxss対策)
$title = htmlspecialchars($_POST["upload_title"]);
$description = htmlspecialchars($_POST["upload_description"], ENT_QUOTES, 'UTF-8');
// 文字数 行数制限
if (strlen($description) > 70){redirectBackPage();}
else if (strlen($title) > 14) {redirectBackPage();}
$description = str_replace("<br>", "", $description);
else if (count(explode("/",$description)) > 5){return;}
$filename = "";
$videoid = "";
// 動画IDをランダム生成
while (!file_exists($filename)){
$videoid = uniqid(rand(), true);
$filename = "../videos/".$videoid.".mp4";
if (!file_exists($filename)){
break;
}
continue;
}
// 動画リストファイルに[動画ID,タイトル,投稿時間,IPのハッシュ値(ユーザーID的な?)]を書き込み
$fp = fopen("../videos/videos.csv", 'ab');
if ($fp){
if (flock($fp, LOCK_EX)){
if (fputcsv($fp, [$videoid, str_replace("'", "\"", $title), date("Y/m/d H:i"), hash("fnv1a32", $_SERVER['REMOTE_ADDR']), $description]) === FALSE){
echo '<script>alert("File write failed.");</script>';
exit;
}
flock($fp, LOCK_UN);
}else{
echo '<script>alert("File lock failed.");</script>';
exit;
}
} else {exit;}
// 動画ファイル書き込み
$uploaded_path = realpath("../videos/mp4/")."/".$videoid.".mp4";
$result = move_uploaded_file($_FILES['upload_video']['tmp_name'],$uploaded_path);
if(!$result){
echo "Upload Error : ".$_FILES['upload_video']['error'];
exit;
}
// ffmpegでhls形式に変換しよう!(最後に&をつけることによってバックグラウンド実行)
exec("ffmpeg -i ".$uploaded_path." -b:v 10M -c:a copy -f hls -hls_playlist_type vod -hls_time 10 -g 24 -hls_segment_filename \"".realpath("../videos/hls/")."/".$videoid."%3d.ts\" ".realpath("../videos/hls/")."/".$videoid.".m3u8 2> ".realpath("../logs")."/".$videoid.".log &");
// 前のページに戻る
redirectBackPage();
cgi-bin/videoList.php 動画リストプログラム
cgi-bin/videoList.php
<?php
$rows = [];
$fp = fopen("videos/videos.csv", 'rb');
if ($fp){
if (flock($fp, LOCK_SH)){
while ($row = fgetcsv($fp)) {
$rows[] = $row;
}
$rows = array_reverse($rows);
if (!empty($rows)){echo "<ul>";}
foreach ($rows as $row){
// 動画リスト出力
$link = "watch?videoid=".$row[0];
echo "<li>".$row[2]."|".$row[3]."</br><a href=".$link.">".$row[1];
if(!file_exists("videos/hls/".$row[0].".m3u8") && !file_exists("videos/mp4/".$row[0].".mp4")){echo "(処理中)";}
echo "</a></li><p style=\"margin-right: 140px;\">";
}
echo "</ul>";
flock($fp, LOCK_UN);
} else {
echo '<script>alert("File lock failed.");</script>';
}
}
fclose($fp);
cgi-bin/watch.php 動画視聴プログラム
cgi-bin/watch.php
<?php
$rows = [];
$videoid = "";
$fp = fopen("videos/videos.csv", 'rb');
if ($fp){
if (flock($fp, LOCK_SH)){
while ($row = fgetcsv($fp)) {
$rows[] = $row;
}
foreach ($rows as $row){
if ($row[0] == $_GET["videoid"]){
$videoid = $row[0];
break;
}
}
if($videoid == "") {redirectBackPage();}
flock($fp, LOCK_UN);
} else {
echo '<script>alert("File lock failed.");</script>';
}
} else {exit;}
3.UIにも少しプログラムを追加
index.html
index.html
<ul class="videoList">
<!-- ここに動画リスト -->
<?php include "cgi-bin/videoList.php" ?>
</ul>
watch.php
watch.php
<?php
function redirectBackPage(){
if (isset($_SERVER['HTTP_REFERER'])){
header("Location: ".$_SERVER['HTTP_REFERER']);
}
exit;
}
date_default_timezone_set('Asia/Tokyo');
if(!isset($_GET["videoid"])){redirectBackPage();}
else if (!file_exists("videos/hls/".$_GET["videoid"].".m3u8") && !file_exists("videos/mp4/".$_GET["videoid"].".mp4")){redirectBackPage();}
include "cgi-bin/watch.php";
?>
<head>
<meta charset="UTF-8" />
<link href="style.css" rel="stylesheet" />
<title>どーがさいと - <?=$row[1]?></title>
</head>
<body>
<h1><?=$row[1]?></h1>
<h3>概要欄</h3>
<pre><?=$row[4]?></pre>
<hr>
<!-- 動画 ここに設置 -->
<?php if(file_exists("videos/hls/".$_GET["videoid"].".m3u8")): ?>
<video controls id="hlsvideo"></video>
<script>
if(Hls.isSupported()) {
var video = document.getElementById('hlsvideo');
var hls = new Hls();
hls.loadSource("videos/hls/<?=$_GET["videoid"]?>.m3u8");
hls.attachMedia(video);
}
</script>
<?php elseif(file_exists("videos/mp4/".$_GET["videoid"].".mp4")): ?>
<video controls id="mp4video" src="videos/mp4/<?=$_GET["videoid"]?>.mp4"></video>
<?php endif; ?>
</body>
4.セットアップ
setup.sh
mkdir videos videos/mp4 videos/hls logs
touch videos/videos.csv
sudo apt install unzip ffmpeg -y
最後に
とりあえずこれで完成かな?
今回のプログラムは完全練習のプログラムなので、いろいろ冗長化かも
Discussion