Skip to content
This repository has been archived by the owner on Nov 22, 2021. It is now read-only.

video's in het fotoboek #34

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a49054c
let updatedb.php include video files (and more)
aykevl Jan 9, 2013
f860f7f
Fixed resolutions (changed to 360p & 720p)
aykevl Jan 9, 2013
4c4116e
bugfix: include albums only containing videos
aykevl Jan 9, 2013
1fb765a
updatecache.php: transcode videos and create thumbnail
aykevl Jan 9, 2013
ba6dc9d
Use a single table for both video and photos
aykevl Jan 9, 2013
2e555d3
Add album thumbnails for videos
aykevl Jan 9, 2013
1dee761
Merge branch 'master' into ayke-video
aykevl Jan 9, 2013
fac03a1
Added video support (should work completely now).
aykevl Jan 10, 2013
c91ce99
Merge branch 'master' into ayke-video
aykevl Jan 10, 2013
6f7826e
Updated $videoExtensions: corrected a few errors
aykevl Jan 10, 2013
6443550
extracted shared code in foto.php and large.php
aykevl Jan 10, 2013
e168ad8
updatecache: Moved shell escaping into transcode() function
aykevl Jan 10, 2013
31af80d
Added options to config.php.sample (warning!)
aykevl Jan 11, 2013
e51c18d
Refactored foto/large/media/thumbnail .php
aykevl Jan 10, 2013
c2e9de6
bugfixes: send good mime; send filename with large.php
aykevl Jan 11, 2013
32f7530
Added support for video under IE7/8 (I hope).
aykevl Jan 11, 2013
994b86f
Added support for video in IE7/8 (I hope) via <object>
aykevl Jan 11, 2013
1d90b4a
Merge branch 'ayke-video' of https://github.com/aykevl93/knfotos into…
aykevl Jan 11, 2013
1948ef5
spelling fix: s/ondersteund/ondersteunt/
aykevl Jan 12, 2013
a08355f
Added locking to updatecache.php and updatedb.php
aykevl Jan 12, 2013
68b98b2
Added warning comment for flock + php on webserver
aykevl Jan 12, 2013
6350218
Added video format prefixes in fa_photos table
aykevl Jan 12, 2013
622e15c
Bugfix in table fa_photos: SQL SET doesn't accept dashes
aykevl Jan 12, 2013
d5e6fdc
Merge branch 'master' into ayke-video (conflict)
aykevl Jan 12, 2013
8f1e719
Let updatecache.php support ffmpeg 0.8.4
aykevl Jan 13, 2013
91c5e96
Added future TODO comment (to remove experimental flag)
aykevl Jan 13, 2013
8edd08b
Merge branch 'master' of github.com:karpenoktem/knfotos into ayke-video
aykevl Jan 13, 2013
d2c1961
Removed unnecessary echos
aykevl Jan 13, 2013
c986a56
Fixed audio bitrate issue (was too big)
aykevl Jan 13, 2013
fdccd8f
bugfixes (vooral error messages gefixt)
aykevl Mar 3, 2013
0bd656f
Merge remote-tracking branch 'upstream/master' into ayke-video
aykevl Sep 30, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion SQL
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ CREATE TABLE `fa_photos` (
`name` varchar(64) NOT NULL,
`path` varchar(255) NOT NULL,
`visibility` enum('deleted','lost','hidden','leden','world') NOT NULL default 'world',
`cached` set('thumb','large','invalidated') NOT NULL,
`cached` set('thumb','large','mp4_360p','webm_360p','mp4_720p','webm_720p','invalidated') NOT NULL,
`rotation` smallint(6) NOT NULL default '0',
`check_tags` tinyint(1) default '0',
`type` enum('photo','video') NOT NULL default 'photo',
PRIMARY KEY (`id`),
UNIQUE KEY `path` (`path`,`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wat is de SQL nodig voor de update?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ik neem aan iets als dit:

alter table fa_photos add column type enum('photo','video');
alter table fa_photos modify column cached set('thumb','large','360p','720p','invalidated');

(niet getest! maar zou moeten werken)

Edit: de tweede regel is nu dit:

alter table fa_photos modify cached set('thumb','large','mp4_360p','webm_360p','mp4_720p','webm_720p','invalidated') NOT NULL;

Deze is wel getest (op de vorige tabelstructuur).
Edit2: extra fix.

Expand Down
16 changes: 15 additions & 1 deletion config.php.sample
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,34 @@
$domain = 'karpenoktem.nl';
$absolute_url_path = '/fotos2/';

// thumbs layout
$thumbs_per_row = 4;
$rows_of_thumbs = 2;

// foto slider
$foto_slider = true;
$foto_slider_preload = true;
$foto_slider_timeout = 5;

// image resize
$imagick = '/usr/local/bin/convert'; // or false to use GD
$thumbnail_size = '100x';
$large_size = '1024x';

// video transcoding
// ffmpeg command (may have extra options)
$ffmpeg = '/usr/local/bin/ffmpeg -loglevel warning';
// put preferred codec first
// note that mp4 (h264) may have hardware acceleration on certain devices
$video_codecs = array('mp4', 'webm');
// when changing these don't forget to update the database table!
// always put lower resolution first!
// and put them in the form of '360p', '480p', '720p', '1080p' etc.
$video_resolutions = array('360p', '720p');

$db_host = 'localhost';
$db_user = 'knfotos';
$db_db = 'knfotos';
$db_db = 'knfotos';
$db_pass = 'abc';

$mongo_host = 'localhost';
Expand Down
30 changes: 30 additions & 0 deletions dbutils.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

// lock the database/cache for write operations
// WARNING: when this is used within a server (non-CLI), the lock will remain
// when the PHP script has finished. When run from the command-line, the locks
// will be relased by the OS (at least, Linux). See:
// http://stackoverflow.com/questions/12651068/release-of-flock-in-case-of-errors
function lock_db () {
global $cachedir;
// provide a locking mechanism to prevent two processes from simultaneously running
$fp = fopen ($cachedir .'lockfile', 'w'); // create if necessary
if (!$fp) {
echo "Could not acquire lock: unable to create lockfile.\n";
}
if (!flock($fp, LOCK_EX|LOCK_NB)) {
echo "Another process is already updating the database/cache.\nIf this isn't true, remove {$cachedir}lockfile.\n";
fclose($fp);
echo "Exiting.\n";
exit;
}
// $fp is required for unlocking (unlocking may be necessary)
return $fp;
}

// unlock again (requires file pointer returned by lock_db)
// this isn't really needed when run from the command line
function unlock_db ($fp) {
flock($fp, LOCK_UN);
fclose($fp);
}
32 changes: 4 additions & 28 deletions foto.php
Original file line number Diff line number Diff line change
@@ -1,36 +1,12 @@
<?php
require('header.php');
require('media.php');

if(!isset($_GET['foto'])) {
showTextAsImage("Missing parameter");
}
$row = getUnitByFullPath($_GET['foto'], UNIT_PHOTO);
if(!$row) {
header('HTTP/1.1 404 Not found');
showTextAsImage('Photo not found');
}
$media = getUnit(UNIT_PHOTO);

if(!in_array($row['visibility'], getVisibleVisibilities()) || !isPathVisible($row['path'])) {
header('HTTP/1.1 403 Access denied');
showTextAsImage('Access denied');
}
$path = $fotodir . $media['path'] . $media['name'];

if(!$mime = $extensions[getext($row['name'])]) {
showTextAsImage("Unknown extension");
}
output($path, $media['name']);

$path = $fotodir . $row['path'] . $row['name'];

if(!is_file($path)) {
header('HTTP/1.1 404 Not found');
showTextAsImage("Image not found");
}
header('Content-type: image/'. $mime);
header('Pragma: public');
header('Cache-Control: public');
header('Last-Modified: '. gmdate('D, d M Y H:i:s', $fmt = filemtime($path)) .' GMT');
header('Expires: '. gmdate('D, d M Y H:i:s', time()+60*60).' GMT');
header('Etag: '. md5($path . $fmt));
readfile($path);
require('footer.php');
?>
38 changes: 29 additions & 9 deletions header.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
require('config.php');

/* Check the config */
if(!isset($fotodir, $cachedir, $domain, $absolute_url_path, $thumbs_per_row, $rows_of_thumbs, $imagick, $thumbnail_size, $foto_slider, $db_host, $db_user, $db_pass, $db_db, $log_queries)) {
if(!isset($fotodir, $cachedir, $domain, $absolute_url_path, $thumbs_per_row, $rows_of_thumbs, $foto_slider, $imagick, $thumbnail_size, $ffmpeg, $video_codecs, $video_resolutions, $db_host, $db_user, $db_pass, $db_db, $log_queries)) {
die("Missing settings");
}
if($log_queries)
Expand Down Expand Up @@ -86,20 +86,40 @@
template_assign('foto_slider_preload');
template_assign('foto_slider_timeout');
}

template_assign('video_codecs');
template_assign('video_resolutions');
}

/* Extensions */
$extensions = array(
'gif' => 'gif',
'jpg' => 'jpeg',
'jpeg' => 'jpeg',
'png' => 'png',
'gif' => 'gif',
$photoExtensions = array(
'gif' => 'gif',
'jpg' => 'jpeg',
'jpeg' => 'jpeg',
'png' => 'png',
);
if($imagick) {
$extensions['bmp'] = 'bmp';
$photoExtensions['bmp'] = 'bmp';
}

$videoExtensions = array(
'3gp' => '3gpp',
'3g2' => '3gpp2',
'avi' => 'video/x-msvideo',
'm4v' => 'x-m4v',
'mkv' => 'x-matroska',
'mpeg' => 'mpeg',
'mpg' => 'mpeg',
'mpe' => 'mpeg',
'mp4' => 'mp4',
'mov' => 'quicktime',
'ogg' => 'ogg',
'ogv' => 'ogg',
'webm' => 'webm',
'wmv' => 'x-ms-wmv',
// this should cover most (and should mostly be usable by ffmpeg)
);

/* Functions */
function show_template($tpl) {
global $_tplvars;
Expand Down Expand Up @@ -298,7 +318,7 @@ function getUnitByFullPath($fullpath, $flags = UNIT_BOTH) {
if($flags & UNIT_PHOTO) {
$res = sql_query("SELECT * FROM fa_photos WHERE path = %s AND name = %s", $path, $name);
if($photo = mysql_fetch_assoc($res)) {
$photo['type'] = 'photo';
// type already defined: 'photo' or 'video'
return $photo;
}
}
Expand Down
3 changes: 3 additions & 0 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@
$mode = 'index';
template_assign('mode');

$type = 'album';
template_assign('type');

template_assign('albums');
template_assign('photos');
if($album != '') {
Expand Down
38 changes: 10 additions & 28 deletions large.php
Original file line number Diff line number Diff line change
@@ -1,37 +1,19 @@
<?php
require('header.php');
require('media.php');

if(!isset($_GET['foto'])) {
header('HTTP/1.1 400 Bad Request');
showTextAsImage("Missing parameter");
}
$row = getUnitByFullPath($_GET['foto'], UNIT_PHOTO);
if(!$row) {
header('HTTP/1.1 404 Not Found');
showTextAsImage('Photo not found');
}
$media = getUnit(UNIT_PHOTO);

if(!in_array($row['visibility'], getVisibleVisibilities()) || !isPathVisible($row['path'])) {
header('HTTP/1.1 403 Access denied');
showTextAsImage('Access denied');
if ($media['type'] == 'photo') {
$path = $cachedir . $media['path'] . $media['name'] .'_large';
} else {
if(!$mime = $videoExtensions[$_GET['codec']]) {
header('HTTP/1.1 400 Bad Request');
}
$path = $cachedir . $media['path'] . $media['name'] .'_'. intval($_GET['res']) .'p.'. $mime;
}

if(!$mime = $extensions[getext($row['name'])]) {
showTextAsImage("Unknown extension");
}
output($path, $media['name']);

$cachepath = $cachedir . $row['path'] . $row['name'] .'_large';

if(!is_file($cachepath)) {
header('HTTP/1.1 404 Not Found');
showTextAsImage("Image not cached", 600);
}
header('Content-type: image/'. $mime);
header('Pragma: public');
header('Cache-Control: public');
header('Last-Modified: '. gmdate('D, d M Y H:i:s', $fmt = filemtime($cachepath)) .' GMT');
header('Expires: '. gmdate('D, d M Y H:i:s', time()+60*60).' GMT');
header('Etag: '. md5($cachepath . $fmt));
readfile($cachepath);
require('footer.php');
?>
44 changes: 44 additions & 0 deletions media.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/* Get current unit (album/photo/video),
wrapper for getUnitByFullPath().
*/
function getUnit ($flags) {
if(!isset($_GET['foto'])) {
header('HTTP/1.1 400 Bad Request');
showTextAsImage("Missing parameter");
}
$row = getUnitByFullPath($_GET['foto'], $flags);
if(!$row) {
header('HTTP/1.1 404 Not Found');
showTextAsImage('Photo not found');
}

if(!in_array($row['visibility'], getVisibleVisibilities()) || !isPathVisible($row['path'])) {
header('HTTP/1.1 403 Access denied');
showTextAsImage('Access denied');
}
return $row;
}

/* Send a file to client.
$path is the path of the file, $name is the original name of the file.
*/
function output ($path, $name=NULL) {
if(!is_file($path)) {
header('HTTP/1.1 404 Not Found');
showTextAsImage("Image not cached", 600);
}

$mime = finfo_file(finfo_open(), $path, FILEINFO_MIME_TYPE);
// hack, as long as webm isn't supported by the magic database, this is needed
if (isset($_GET['codec']) && $_GET['codec'] == 'webm') {
$mime = 'video/webm';
}

if ($name)
// send real filename instead of php file name
header('Content-disposition: inline; filename='. $name);
header('Content-type: '. $mime);
header('X-Sendfile: '. $path);
}
67 changes: 67 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use strict';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:)

function slider_next() {
location.href = next;
}

function slider_preload() {
var el=document.createElement('img');
el.src= preload;
el.style.display = 'none';
el.alt = 'Fotoslider Preloader';
document.body.appendChild(el);
}

// apply change in resolution to <video>
function updateResolution () {
var resolution = document.getElementById('resolution').value;
localStorage.videoResolution = resolution;
var video = document.getElementById('video');
var codec = null;
for (var i=0; i<codecs.length; i++) {
if (video.canPlayType('video/'+codecs[i])) {
codec = codecs[i];
}
}
if (!codec) {
// problem! Just choose the first. It probably won't play anyway.
codec = codecs[0];
}
// workaround for bug in Chrome on Linux (mp4 doesn't play but is still advertized to play)
if (video.canPlayType('video/webm') && navigator.userAgent.indexOf('Linux') && navigator.userAgent.indexOf('Chrome') && codecs.indexOf('webm') != -1) {
codec = 'webm';
}
// all browsers supporting <video> support querySelector
var src = document.querySelector('source[type="video/'+codec+'"][data-resolution="'+resolution+'"]').src;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is dat standaard javascript? Werkt dat in alle browsers? Gaaf.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ja. Het werkt in alle browsers die <video> ondersteunen. En zonder

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je zin klopt niet. Bedoel je "die we ondersteunen" of "die het ondersteunen"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oeps. De browsers die <video> ondersteunen. Volgens mij kwam ik net uit bed...

var position = video.currentTime;
var playing = !video.paused;
video.src = src;
video.addEventListener('loadedmetadata', function () {
video.currentTime = position;
if (playing)
video.play();
}, false);
}

if (type == 'photo') {
if (sliding) {
setTimeout('slider_next()', slider_timeout*1000);
}
} else if (type == 'video') {
window.addEventListener('DOMContentLoaded', function () {
var video = document.getElementById('video');
if (document.getElementById('resolution').value != localStorage.videoResolution) {
if (localStorage.videoResolution)
document.getElementById('resolution').value = localStorage.videoResolution;
updateResolution();
}
if (sliding) {
video.addEventListener('ended', function () {
// don't jump to the next immediately
setTimeout(function () {
if (!video.paused) return;
slider_next();
}, 1000);
}, false);
}
}, false);
}
26 changes: 12 additions & 14 deletions templates/header.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,20 @@
<![endif]-->
<link href="https://www.karpenoktem.nl/base/styles/common/" rel="stylesheet" type="text/css" />
<link type="text/css" rel="stylesheet" href="style.css" />
<?PHP if($sliding) { ?>
<script type="text/javascript">
function slider_next() {
location.href="view.php?slide&foto=<?= urlencode($next) ?>";
}
<?PHP if($foto_slider_preload) { ?>
function slider_preload() {
var el=document.createElement('img');
el.src='foto.php?foto=<?= urlencode($next) ?>';
el.style.display='none';
el.alt='Fotoslider Preloader';
document.body.appendChild(el);
}
<?PHP } ?>
setTimeout('slider_next()', <?= $foto_slider_timeout*1000 ?>);
var sliding = <?= $sliding ? 'true' : 'false' ?>;
<?php if ($sliding) { ?>
var next = "view.php?slide&foto=<?= urlencode($next) ?>";
<?php if ($foto_slider_preload) { ?>
var preload = 'foto.php?foto=<?= urlencode($next) ?>';
<?php } ?>
var slider_timeout = <?= $foto_slider_timeout ?>;
<?php } ?>
var type = '<?= $type ?>';
var codecs = <?= json_encode($video_codecs) ?>;
</script>
<script type="text/javascript" src="script.js"></script>
<?PHP if($sliding) { ?>
<noscript>
<meta http-equiv="refresh" content="<?= $foto_slider_timeout ?>; url=view.php?slide&foto=<?= urlencode($next) ?>">
</noscript>
Expand Down
Loading