動画配信サイトを自作してみる

自分用の動画配信サイトが欲しいなって思ったのが作ろうと思ったきっかけです。

初めにサーバーを用意しなければいけないのですが、普通のウェブサーバーではもの足りません。

なぜなら、動画のエンコードや結合をおこなえないからです。

その為今回はVPSや自宅鯖という手段を使っていることを前提として話を進めさせていただきます。

 

1.初期設定

必要なアプリケーションをインストールします

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install apache php php-mbstring ffmpeg

次に php.ini を設定します。

変更する箇所は

memory_limit

post_max_size

upload_max_filesize

になります

memory_limit = 1024M
post_max_size = 1024M
upload_max_filesize = 1024M

今回は1024M (1G)までのファイルをアップロードできるようにします。

クラウドフレアというサービスを利用している場合は最大100Mとなるので注意してください。

また、memory_limit の値は post_max_size より多くしてください。

設定できたら

sudo apache2ctl restart

を実行しサーバーを再起動させます。

 

2.データベース設計

動画のメタ情報を管理するためにMySQLサーバーを使用します。

テーブル構造を考えた時に、初めにユーザーアカウント情報、動画情報は最低でも必要になるので先に作成しておきます。コメントなどは後からでも追加できるので今回はパスです。

create table user(
id int not null auto_increment primary key,
created_at datetime default current_timestamp,
username varchar(30) not null,
password varchar(30) not null
)

create table video(
id varchar(20) not null primary key,
created_at datetime default current_timestamp,
author int not null,
title varchar(50) not null,
description text not null,
publish int not null default 1
)

user テーブルの解説から行います。

id はユーザーごとにことなるキーのプライマリキーになります。

created_at はユーザーを作成した日時になります。

username、password はそのままの意味です。

video テーブルの解説に入ります。

id は動画ごとに異なる特別なキーになり、これが動画を視聴する際に必要となります。

created_at は動画が投稿(INSERT)されたときの日時になります。

author は投稿者IDになります。user テーブルのid がこれにあたります。

title、description はそのままの意味です。

publish は公開状況です。

0 は非公開 1 は公開 です。

 

3.コーディング

コーディングといってもHTMLでフォームを作成して、PHPで処理するだけです。

HTML のフォームは今回割愛させていただきます。

<?php

function makeRandStr($length = 12) { $str = array_merge(range('a', 'z'), range('0', '9'), range('A', 'Z')); $r_str = null; for ($i = 0; $i < $length; $i++) { $r_str .= $str[rand(0, count($str) - 1)]; } return $r_str; }
$file = $_FILES["upload"];
$path = makeRandStr() . ".mp4";
move_uploaded_file($file["tmp_name"], $path);

エラーチェックもろもろしてません。

本番環境ではしてくださいね。

次にコマンドラインをたたかせてFFMPEGを実行させます。

今回はサムネイルの作成を行います。

shell_exec("nohup ffmpeg -i " . $path . " -pix_fmt yuvj422p -deinterlace -an -ss 0 -f mjpeg -t 1 -r 1 -y -s 1280x720 " . $path . ".jpg > /dev/null &");

あとはデータベースに動画の情報を挿入して完了です。

返信機能付きの一行掲示板を作成する

返信機能付きの一行掲示板を今回は作成しようと思うのですが、まず始めに基本となる一行掲示板を作成してから追加機能として返信機能を付けたいと思います。

ですので既存のツールに組み込むことができるかもしれません。よかったら参考にしてみてください。

 

一行掲示板

初めにデータベースの設計を考えます。

データベースの設計は重要です。再構築するとなると全データを移動させる必要があるので面倒になります。先にしっかりと考えましょう。

今回は以下のような構造体にします。

id int not null auto_increment primary key
user varchar(30) not null
message text not null
reply tinyint(1) default 0
replyId int
date datetime default current_timestamp

解説をすると、

id はそのデータの固有IDとなります。

返信をする際に必要となります。

user は投稿主の名前です。

message は投稿内容です。

reply は 0 か 1 によって、返信かどうかを見分けるためのフラグです。

replyId は返信先の固有IDです。

date は投稿された日時です。自動的にMYSQLサーバーのタイムスタンプを割り当てています。

 

フォームの宛先を雑ですが書くと

<?php

$pdo = new PDO(/* あらかじめ作成しておく */);
$user = filter_input(INPUT_POST, "user");
$message = filter_input(INPUT_POST, "message");
$isReply = filter_input(INPUT_POST, "reply") == null ? 0 : 1;
$repId = filter_input(INPUT_POST, "replyId");

if ($isReply) {
$sql = "insert into bbs(user, message, reply, replyId) values(:user, :message, 1, :replyId)";
} else {
$sql = "insert into bbs(user, message) values(:user, :message)";
}

$smt = $pdo->prepare($sql);
$smt->execute(/* 必要な値を配列で渡す */);

のような形になります(雑だけど)。

※受け取った値は必ず 「htmlspecialchars」などの関数を使用してパースしてください。

※本番環境ではNULLチェックだとか、TRY CATCH とかしてね☆

 

トップページ用のSQLは

select * from bbs where reply=0;

返信表示用のページ(SNS風にするのであれば)は

select * from bbs where reply=1 replyId={$ID};

のようにすればOKだと思います!

 

以上で一行掲示板返信機能付きの解説(じゃないですねすいません)でした

このままだと認証(アカウント機能)やスパム対策がないので追加していかなければいけませんね。

ffmpeg による動画の圧縮処理

今回、とあるウェブサービスを実装するにあたり動画を圧縮する必要が出てきた。

圧縮すると画質は劣化するけど、容量を抑えるためには必須だよね。

 

それで

・サーバー上で実行できること

・コマンドラインで実行できること

・情報が豊富であること

の3拍子揃ったFFMPEGを使うことにした。

使い方はとってもシンプルだった。

mp4 から webm への変換は

$ ffmpeg -i input.mp4 output.webm

これだけ少し待てば output.webm が生成される。

容量はテスト動画だと2分の1になった。

画質は少し文字が見にくくなっている(ぼやけてる)

人によっては嫌う。

 

この処理をバックグラウンドで非同期に行うには

$ nohup ffmpeg -i input.mp4 output.webm > /dev/null &

でOK

> /dev/null はログを捨てていて

& で非同期にさせている