300 lines
13 KiB
PHP
300 lines
13 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Carbon\Carbon;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
use Cviebrock\EloquentTaggable\Services\TagService;
|
|
|
|
/**
|
|
* App\Models\Video
|
|
*
|
|
* @property integer $id
|
|
* @property string $file
|
|
* @property string $interpret
|
|
* @property string $songtitle
|
|
* @property string $imgsource
|
|
* @property integer $category_id
|
|
* @property integer $user_id
|
|
* @property \Carbon\Carbon $created_at
|
|
* @property \Carbon\Carbon $updated_at
|
|
* @property string $deleted_at
|
|
* @property string $hash
|
|
* @property-read User $user
|
|
* @property-read Category $category
|
|
* @property-read \Illuminate\Database\Eloquent\Collection|Comment[] $comments
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video whereId($value)
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video whereFile($value)
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video whereInterpret($value)
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video whereSongtitle($value)
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video whereImgsource($value)
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video whereCategoryId($value)
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video whereUserId($value)
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video whereCreatedAt($value)
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video whereUpdatedAt($value)
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video whereDeletedAt($value)
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video whereHash($value)
|
|
* @property-read \Illuminate\Database\Eloquent\Collection|User[] $faved
|
|
* @property-read \Illuminate\Database\Eloquent\Collection|Tag[] $tags
|
|
* @property-read mixed $tag_list
|
|
* @property-read mixed $tag_list_normalized
|
|
* @property-read mixed $tag_array
|
|
* @property-read mixed $tag_array_normalized
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video newlyups()
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video withAllTags($tags)
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video withAnyTags($tags = array())
|
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Video withoutTags()
|
|
*/
|
|
class Video extends Model
|
|
{
|
|
use SoftDeletes;
|
|
use \Cviebrock\EloquentTaggable\Taggable;
|
|
|
|
public function user() {
|
|
return $this->belongsTo(User::class);
|
|
}
|
|
|
|
public function category() {
|
|
return $this->belongsTo(Category::class);
|
|
}
|
|
|
|
public function comments() {
|
|
return $this->hasMany(Comment::class);
|
|
}
|
|
|
|
public function faved() {
|
|
return $this->belongsToMany(User::class, 'favorites', 'video_id', 'user_id');
|
|
}
|
|
|
|
public function hasAllTags($tags) {
|
|
$tags = app(TagService::class)->buildTagArrayNormalized($tags);
|
|
$videotags = $this->getTagArrayNormalizedAttribute();
|
|
foreach ($tags as $t) {
|
|
if (!in_array($t,$videotags)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static function getFirstId($related = null, $isTag = false) {
|
|
if ($related) {
|
|
if (!$isTag) {
|
|
return $related->videos()->filtered()->orderBy('id', 'ASC')->first()->id;
|
|
}
|
|
$related = app(TagService::class)->buildTagArray($related);
|
|
return Video::withAllTags($related)->filtered()->orderBy('id', 'ASC')->first()->id;
|
|
}
|
|
return static::filtered()->orderBy('id', 'ASC')->first()->id;
|
|
}
|
|
|
|
public static function getLastId($related = null, $isTag = false) {
|
|
if ($related) {
|
|
if (!$isTag) {
|
|
return $related->videos()->filtered()->orderBy('id', 'DESC')->first()->id;
|
|
}
|
|
$related = app(TagService::class)->buildTagArray($related);
|
|
return Video::withAllTags($related)->filtered()->orderBy('id', 'DESC')->first()->id;
|
|
}
|
|
return static::select('id')->filtered()->orderBy('id', 'DESC')->first()->id;
|
|
}
|
|
|
|
public function getNext($related = null, $isTag = false) {
|
|
if ($related) {
|
|
if (!$isTag) {
|
|
return $related->videos()->filtered()->where('id', '>', $this->id)->orderBy('id', 'ASC')->first();
|
|
}
|
|
$related = app(TagService::class)->buildTagArray($related);
|
|
return Video::withAllTags($related)->filtered()->where('id', '>', $this->id)->orderBy('id', 'ASC')->first();
|
|
} else {
|
|
return static::filtered()->where('id', '>', $this->id)->orderBy('id', 'ASC')->first();
|
|
}
|
|
}
|
|
|
|
public function getPrev($related = null, $isTag = false) {
|
|
if ($related) {
|
|
if (!$isTag) {
|
|
return $related->videos()->filtered()->where('id', '<', $this->id)->orderBy('id', 'DESC')->first();
|
|
}
|
|
$related = app(TagService::class)->buildTagArray($related);
|
|
return Video::withAllTags($related)->filtered()->where('id', '<', $this->id)->orderBy('id', 'DESC')->first();
|
|
} else {
|
|
return static::filtered()->where('id', '<', $this->id)->orderBy('id', 'DESC')->first();
|
|
}
|
|
}
|
|
|
|
public function scopeNewlyups($query) {
|
|
return $query->where('created_at', '>=', Carbon::now()->subHours(12));
|
|
}
|
|
|
|
public function scopeFiltered($query) {
|
|
if(auth()->check()) {
|
|
// TODO rename to filtered
|
|
$filter = auth()->user()->categories;
|
|
if(empty($filter))
|
|
return $query;
|
|
|
|
return $query->withoutAnyTags($filter);
|
|
} else {
|
|
// TODO: filter if post has sfw & nsfw tags
|
|
//return $query->withAllTags('sfw');
|
|
return $query->withoutAnyTags('nsfw');
|
|
|
|
}
|
|
}
|
|
|
|
public function checkFileEncoding() {
|
|
$dat = $this->file;
|
|
$in = public_path() . "/b";
|
|
$tmpdir = str_replace("public", "app/Http/Controllers/tmp", public_path());
|
|
for($i = 0; $i < 2; $i++) {
|
|
$ret = shell_exec("ffmpeg -y -ss 0 -i {$in}/{$dat} -vframes 1 {$tmpdir}/test.png 2>&1");
|
|
if(strpos($ret, "nothing was encoded") !== false) {
|
|
shell_exec("ffmpeg -i {$in}/{$dat} -map 0:0 -map 0:1 -c:v copy {$tmpdir}/{$dat}");
|
|
unlink($in . "/" . $dat);
|
|
rename($tmpdir . "/" . $dat, $in . "/" . $dat);
|
|
}
|
|
else return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Creates a .gif thumbnail to a given video file
|
|
*
|
|
* @param string $dat File of the video
|
|
*/
|
|
public function createThumbnail() {
|
|
$dat = $this->file;
|
|
$in = public_path() . "/b"; // webm-input
|
|
$out = public_path() . "/thumbs"; //thumb-output
|
|
$tmpdir = str_replace("public", "app/Http/Controllers/tmp", public_path());
|
|
|
|
$name = explode(".", $dat);
|
|
array_pop($name);
|
|
$name = join(".", $name);
|
|
if(!file_exists("{$out}/{$name}.gif")) {
|
|
$length = round(shell_exec("ffprobe -i {$in}/{$dat} -show_format -v quiet | sed -n 's/duration=//p'"));
|
|
for ($i = 1; $i < 10; $i++) {
|
|
$act = ($i * 10) * ($length / 100);
|
|
$ffmpeg = shell_exec("ffmpeg -ss {$act} -i {$in}/{$dat} -vf \"scale='if(gt(a,4/3),206,-1)':'if(gt(a,4/3),-1,116)'\" -vframes 1 {$tmpdir}/{$name}_{$i}.png 2>&1");
|
|
}
|
|
$tmp = shell_exec("convert -delay 27 -loop 0 {$tmpdir}/{$name}_*.png {$out}/{$name}.gif 2>&1");
|
|
if(@filesize("{$out}/{$name}.gif") < 2000)
|
|
@unlink("{$out}/{$name}.gif");
|
|
array_map('unlink', glob("{$tmpdir}/{$name}*.png"));
|
|
}
|
|
}
|
|
|
|
public function tesThumb() {
|
|
set_time_limit(9899999999999999);
|
|
$dat = $this->file;
|
|
$in = public_path() . "/b"; // webm-input
|
|
#$in = "/home/w0bm/w0bm/public/b";
|
|
$out = public_path() . "/thumbs/beta"; //thumb-output
|
|
$tmpdir = str_replace("public", "app/Http/Controllers/tmp", public_path());
|
|
|
|
$name = explode(".", $dat);
|
|
array_pop($name);
|
|
$name = join(".", $name);
|
|
|
|
#$ffmpegthumbnailer = round(shell_exec("ffmpegthumbnailer -i {$in}/{$dat} -a -o {$out}/{$name}_test.png"));
|
|
//$ffmpeg = round(shell_exec("ffmpeg -i {$in}/{$dat} -vf select='eq(pict_type,PICT_TYPE_I)' -vf scale=128:128 {$out}/{$name}_ffmpeg.png"));
|
|
$length = round(shell_exec("ffprobe -i {$in}/{$dat} -show_format -v quiet | sed -n 's/duration=//p'"));
|
|
$half = $length / 20;
|
|
$ffmpeg = exec("ffmpegthumbnailer -i {$in}/{$dat} -o {$out}/{$name}_test.png", $output, $return);
|
|
if ($return != 0) {
|
|
// error
|
|
@unlink("{$out}/{$name}_test.png");
|
|
exec("ffmpeg -i {$in}/{$dat} -vf select='eq(pict_type,PICT_TYPE_I)' -vf scale=128:128:force_original_aspect_ratio=increase,crop=128:128 {$out}/{$name}.png");
|
|
}else{
|
|
// success
|
|
@unlink("{$out}/{$name}_test.png");
|
|
exec("ffmpeg -i {$in}/{$dat} -vf select='eq(pict_type,PICT_TYPE_I)' -vf scale=128:128:force_original_aspect_ratio=increase,crop=128:128 -ss {$half} {$out}/{$name}.png");
|
|
}
|
|
}
|
|
|
|
public function blurryThumb() {
|
|
set_time_limit(9899999999999999);
|
|
$dat = $this->file;
|
|
#$in = public_path() . "/b"; // webm-input
|
|
$in = public_path() . "/b";
|
|
$out = public_path() . "/thumbs/blurred"; //thumb-output
|
|
$tmpdir = str_replace("public", "app/Http/Controllers/tmp", public_path());
|
|
|
|
$name = explode(".", $dat);
|
|
array_pop($name);
|
|
$name = join(".", $name);
|
|
|
|
#$ffmpegthumbnailer = round(shell_exec("ffmpegthumbnailer -i {$in}/{$dat} -a -o {$out}/{$name}_test.png"));
|
|
//$ffmpeg = round(shell_exec("ffmpeg -i {$in}/{$dat} -vf select='eq(pict_type,PICT_TYPE_I)' -vf scale=128:128 {$out}/{$name}_ffmpeg.png"));
|
|
$length = round(shell_exec("ffprobe -i {$in}/{$dat} -show_format -v quiet | sed -n 's/duration=//p'"));
|
|
$half = $length / 20;
|
|
$ffmpeg = exec("ffmpegthumbnailer -i {$in}/{$dat} -o {$out}/{$name}_testblur.png", $output, $return);
|
|
if ($return != 0) {
|
|
// error
|
|
@unlink("{$out}/{$name}_testblur.png");
|
|
exec("ffmpeg -i {$in}/{$dat} -vf select='eq(pict_type,PICT_TYPE_I)' -vf scale=128:128:force_original_aspect_ratio=increase,crop=128:128 {$out}/{$name}.png");
|
|
exec("convert {$out}/{$name}.png -blur 0x8 {$out}/{$name}_blurred.png");
|
|
@unlink("{$out}/{$name}.png");
|
|
}else{
|
|
// success
|
|
@unlink("{$out}/{$name}_testblur.png");
|
|
exec("ffmpeg -i {$in}/{$dat} -vf select='eq(pict_type,PICT_TYPE_I)' -vf scale=128:128:force_original_aspect_ratio=increase,crop=128:128 -ss {$half} {$out}/{$name}.png");
|
|
exec("convert {$out}/{$name}.png -blur 0x8 {$out}/{$name}_blurred.png");
|
|
@unlink("{$out}/{$name}.png");
|
|
}
|
|
}
|
|
|
|
public static function getRandom($related = null, $tag = false) {
|
|
if ($related) {
|
|
if (!$tag) {
|
|
$id = $related->videos()->filtered()->countScoped()->count() - 1;
|
|
if ($id < 0) {
|
|
return redirect()->back()->with('error', 'no videos found');
|
|
}
|
|
$id = mt_rand(0, $id);
|
|
return $related->videos()->filtered()->skip($id);
|
|
}
|
|
// jetzt sind wir im tag
|
|
$related = app(TagService::class)->buildTagArray($related);
|
|
$id = Video::withAllTags($related)->filtered()->countScoped()->count()-1;
|
|
|
|
if ($id < 0) {
|
|
return redirect()->back()->with('error', 'no videos found');
|
|
}
|
|
$id = mt_rand(0,$id);
|
|
return Video::withAllTags($related)->filtered()->skip($id);
|
|
|
|
}
|
|
$id = static::filtered()->countScoped()->count() - 1;
|
|
if ($id < 0) {
|
|
return redirect()->back()->with('error', 'no videos found');
|
|
}
|
|
$id = mt_rand(0, $id);
|
|
return static::filtered()->skip($id);
|
|
}
|
|
|
|
|
|
public static function getSingleRandom($related = null) {
|
|
$query = $related ? $related->videos()->filtered() : static::filtered();
|
|
$count = $query->countScoped()->count();
|
|
if ($count < 1) {
|
|
return null; // Return null if no videos found
|
|
}
|
|
return $query->inRandomOrder()->first();
|
|
}
|
|
|
|
public function isSfw() {
|
|
return !$this->tags->contains(function ($key, $tag) {
|
|
return $tag->normalized === 'nsfw';
|
|
});
|
|
}
|
|
|
|
public function filesize() {
|
|
return filesize(getcwd() . "/b/" . $this->file);
|
|
}
|
|
}
|