diff --git a/trunk/locale/en-us.xml b/trunk/locale/en-us.xml index 4abc5a3..26e2aed 100755 --- a/trunk/locale/en-us.xml +++ b/trunk/locale/en-us.xml @@ -3,202 +3,202 @@ -  |  +  |  - - to upload videos, log in first. + + to upload videos, log in first. - register - login - login with OpenID + register + login + login with OpenID - upload video - settings details + upload video + settings details - logged in as  - logout + logged in as  + logout - - © 2007 - 2008 Yolanda Team - - This software comes WITHOUT ANY WARRANTY; without even the implied warranty of + + © 2007 - 2008 Yolanda Team + + This software comes WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for details. - view license - get source code - report bug - view this page as xml - + view license + get source code + report bug + view this page as xml + - - Find - Instant Access - Advanced Search + + Find + Instant Access + Advanced Search - latest additions - most downloaded - most viewed + latest additions + most downloaded + most viewed - - Error 202c - Access forbidden by government. - You did not supply a file. - You did not supply a title. - You did not supply a creator. - You did not supply any keywords. - You did not supply a description. - You did not supply a publisher. - You did not supply a title. - You did not supply a source. - You did not supply a language. - You did not supply a coverage. - You did not supply a rights holder. - You seem to be already registered. Please log out to create a new account. - You seem to be already logged in. Please log out to log in again. - Username and password do not match. - Passwords do not match. - Your desired Username was already registered - Please insert a username. - Please insert a password. - Please repeat your password. - You passed no query string. - + + Error 202c - Access forbidden by government. + You did not supply a file. + You did not supply a title. + You did not supply a creator. + You did not supply any keywords. + You did not supply a description. + You did not supply a publisher. + You did not supply a title. + You did not supply a source. + You did not supply a language. + You did not supply a coverage. + You did not supply a rights holder. + You seem to be already registered. Please log out to create a new account. + You seem to be already logged in. Please log out to log in again. + Username and password do not match. + Passwords do not match. + Your desired Username was already registered + Please insert a username. + Please insert a password. + Please repeat your password. + You passed no query string. + - - You are now logged in. - You are now logged out. - To put the video into context, additional metainformation is needed. - - Your comment has been submitted. - Your account has been created. - Your file has been uploaded. - Your successfully changed your settings. + + You are now logged in. + You are now logged out. + To put the video into context, additional metainformation is needed. + + Your comment has been submitted. + Your account has been created. + Your file has been uploaded. + Your successfully changed your settings. - - There are no results satisfying your query. + + There are no results satisfying your query. - - results - to - out of - - ordered by - ascending - descending - oldest first - most recent first - least downloaded first - most downloaded first - least viewed first - most viewed first - shortest first - lenghtest first - smallest first - biggest first - results on - pages - relevance - duration - filesize - views - downloads - timestamp - - - search - - - username - password - repeat password - register - login + + results + to + out of + + ordered by + ascending + descending + oldest first + most recent first + least downloaded first + most downloaded first + least viewed first + most viewed first + shortest first + lenghtest first + smallest first + biggest first + results on + pages + relevance + duration + filesize + views + downloads + timestamp + + + search + + + username + password + repeat password + register + login - - file - continue - upload - Basic Information - Similar Videos - Additional Metainformation - Licensing - Summary / Upload - Describe the video you want to upload. - Similar videos have already been uploaded. If none of these videos matches yours, continue. - Providing these infos helps us to put the video into context. - Describe the video's license. - Double-check the data and correct mistakes, if necessary. - Specify the file you want to upload. - State the title of the video. - Specify the creator of the video. - State some keywords, separated by spaces. - Describe the video in natural language. - Specify the source, preferably by URL. - State the language of the video. - Specify the time and location covered. - Specify the copyright owner of the video. - Specify the license, preferably by URL. - Optionally, choose Creative Commons licensing. - Permit modification. - Permit modification, derivatives must use the same license. - Prohibit modification. - Prohibit commercial use. - This is page 1 of 5. - This is page 2 of 5. - This is page 3 of 5. - This is page 4 of 5. - This is page 5 of 5. - back to page 1 - back to page 3 - back to page 4 + + file + continue + upload + Basic Information + Similar Videos + Additional Metainformation + Licensing + Summary / Upload + Describe the video you want to upload. + Similar videos have already been uploaded. If none of these videos matches yours, continue. + Providing these infos helps us to put the video into context. + Describe the video's license. + Double-check the data and correct mistakes, if necessary. + Specify the file you want to upload. + State the title of the video. + Specify the creator of the video. + State some keywords, separated by spaces. + Describe the video in natural language. + Specify the source, preferably by URL. + State the language of the video. + Specify the time and location covered. + Specify the copyright owner of the video. + Specify the license, preferably by URL. + Optionally, choose Creative Commons licensing. + Permit modification. + Permit modification, derivatives must use the same license. + Prohibit modification. + Prohibit commercial use. + This is page 1 of 5. + This is page 2 of 5. + This is page 3 of 5. + This is page 4 of 5. + This is page 5 of 5. + back to page 1 + back to page 3 + back to page 4 - - English - German + + English + German - - download - mark as junk - edit - MB - use browser plugin - use java applet - license conditions - To embed the video on another web page, use the following HTML code: - login to comment - post + + download + mark as junk + edit + MB + use browser plugin + use java applet + license conditions + To embed the video on another web page, use the following HTML code: + login to comment + post - - backlink + + backlink - - title - author - keywords - description - uploader - contributor - upload date - source - language - coverage - rights holder - license + + title + author + keywords + description + uploader + contributor + upload date + source + language + coverage + rights holder + license - duration - viewcount + duration + viewcount - - account settings - locale - choose pagesize - choose your preferred method of video playback. + + account settings + locale + choose pagesize + choose your preferred method of video playback. - -  -  - this page - all results - This is an RSS Feed for the query " - ". + +  -  + this page + all results + This is an RSS Feed for the query " + ". diff --git a/trunk/site/main.xml b/trunk/site/main.xml index b70ab7e..1b8a8f4 100755 --- a/trunk/site/main.xml +++ b/trunk/site/main.xml @@ -3,27 +3,27 @@ - - Yolanda - WebTV free as in Speech + + Yolanda + WebTV free as in Speech - - /settings.pl - /login.pl - /login.pl?action=openid - /login.pl?action=logout - http://yolanda.mister-muffin.de/trac - /LICENSE - http://yolanda.mister-muffin.de/trac/browser/trunk - /register.pl - http://yolanda.mister-muffin.de/trac/newticket - /search.pl?query= - http://localhost/ - /upload.pl - /uploader.pl - /search.pl?query=orderby:timestamp%20sort:descending - /search.pl?query=orderby:downloadcount%20sort:descending - /search.pl?query=orderby:viewcount%20sort:descending + + /settings.pl + /login.pl + /login.pl?action=openid + /login.pl?action=logout + http://yolanda.mister-muffin.de/trac + /LICENSE + http://yolanda.mister-muffin.de/trac/browser/trunk + /register.pl + http://yolanda.mister-muffin.de/trac/newticket + /search.pl?query= + http://localhost/ + /upload.pl + /uploader.pl + /search.pl?query=orderby:timestamp%20sort:descending + /search.pl?query=orderby:downloadcount%20sort:descending + /search.pl?query=orderby:viewcount%20sort:descending diff --git a/trunk/style/default.css b/trunk/style/default.css index 3de5beb..6e1c867 100755 --- a/trunk/style/default.css +++ b/trunk/style/default.css @@ -7,383 +7,382 @@ Yolanda default stylesheet * { - clear: both; + clear: both; } body { - font-family: sans-serif; - font-size: 8pt; - font-weight: bold; - margin: 1.5em; - min-height: 100%; - text-align: center; + font-family: sans-serif; + font-size: 8pt; + font-weight: bold; + margin: 1.5em; + min-height: 100%; + text-align: center; } div { - border-width: 0px; + border-width: 0px; } input { - text-align: left; + text-align: left; } img { - border-width: 0; + border-width: 0; } /* links */ a { - color: #3f3fff; - text-decoration: none; + color: #3f3fff; + text-decoration: none; } - a:focus - { - font-style: italic; - } + a:focus + { + font-style: italic; + } - a:hover - { - text-decoration: underline; - } + a:hover + { + text-decoration: underline; + } - a.tag - { - display: inline-block; - margin-left: 0.25em; - margin-right: 0.25em; - } + a.tag + { + display: inline-block; + margin-left: 0.25em; + margin-right: 0.25em; + } /* header, footer */ - a.footer, - a.header, - div.footer, - div.header - { - background-color: #f0f0f0; - border-color: #f0f0f0; - border-style: solid; - clear: none; - font-size: 1em; - line-height: 3em; - height: 3em; - } + a.footer, + a.header, + div.footer, + div.header + { + background-color: #f0f0f0; + border-color: #f0f0f0; + border-style: solid; + clear: none; + font-size: 1em; + line-height: 3em; + height: 3em; + } - a.footer, - a.header - { - border-bottom-width: 0px; - border-top-width: 0px; - border-left-width: 1px; - border-right-width: 1px; - display: block; - padding-left: 1em; - padding-right: 1em; - } + a.footer, + a.header + { + border-bottom-width: 0px; + border-top-width: 0px; + border-left-width: 1px; + border-right-width: 1px; + display: block; + padding-left: 1em; + padding-right: 1em; + } - a.footer:hover, - a.header:hover - { - background-color: #ffffff; - border-color: #c0c0c0; - } + a.footer:hover, + a.header:hover + { + background-color: #ffffff; + border-color: #c0c0c0; + } - a.latest-additions, - a.view-license - { - border-left-width: 0px; - } + a.latest-additions, + a.view-license + { + border-left-width: 0px; + } - a.register, - a.upload-video, - a.view-xml - { - border-right-width: 0px; - } + a.register, + a.upload-video, + a.view-xml + { + border-right-width: 0px; + } - a.latest-additions, - a.most-downloads, - a.most-views, - a.report-bug, - a.view-license, - a.view-source-code - { - float: left; - } + a.latest-additions, + a.most-downloads, + a.most-views, + a.report-bug, + a.view-license, + a.view-source-code + { + float: left; + } - a.login, - a.login-openid, - a.logout, - a.preferences, - a.register, - a.upload-video, - a.view-xml - { - float: right; - } + a.login, + a.login-openid, + a.logout, + a.preferences, + a.register, + a.upload-video, + a.view-xml + { + float: right; + } - div.footer, - div.header - { - border-color: #c0c0c0; - border-width: 1px; - } + div.footer, + div.header + { + border-color: #c0c0c0; + border-width: 1px; + } - div.footer - { - position: absolute; - bottom: 1.5em; - margin-right: 1.5em; - } - - img.logo-header - { - display: none; - border: 1px black solid; - clear: none; - float: left; - margin-left: 1.5em; - margin-right: 0.5em; - } + div.footer + { + position: absolute; + bottom: 1.5em; + margin-right: 1.5em; + } + img.logo-header + { + display: none; + border: 1px black solid; + clear: none; + float: left; + margin-left: 1.5em; + margin-right: 0.5em; + } /* content */ - div.button-download, - div.button-edit, - div.button-junk - { - display: inline-block; - margin: 0.5em; - vertical-align: top; - } + div.button-download, + div.button-edit, + div.button-junk + { + display: inline-block; + margin: 0.5em; + vertical-align: top; + } - div.button-download img, - div.button-edit img, - div.button-junk img - { - margin: 0.5em; - } + div.button-download img, + div.button-edit img, + div.button-junk img + { + margin: 0.5em; + } - div.cc-license-chooser - { - } + div.cc-license-chooser + { + } - div.cc-license-chooser img - { - margin: 0.25em; - vertical-align: middle; - } + div.cc-license-chooser img + { + margin: 0.25em; + vertical-align: middle; + } - div.commentform, - div.loginform, - div.registerform, - div.settingsform, - div.uploadform - { - line-height: 2.5em; - margin: 1.5em; - } + div.commentform, + div.loginform, + div.registerform, + div.settingsform, + div.uploadform + { + line-height: 2.5em; + margin: 1.5em; + } - div.comments - { - } + div.comments + { + } - div.messagebox - { - border-color: #606060; - border-style: solid; - border-width: 1px; - margin: 1.5em; - } + div.messagebox + { + border-color: #606060; + border-style: solid; + border-width: 1px; + margin: 1.5em; + } - div.messagebox#error, - div.messagebox#warning - { - background-color: #f09090; - } + div.messagebox#error, + div.messagebox#warning + { + background-color: #f09090; + } - div.messagebox#information - { - background-color: #90f090; - } + div.messagebox#information + { + background-color: #90f090; + } - div.messagebox img - { - margin: 0.75em; - overflow: visible; - vertical-align: middle; - } + div.messagebox img + { + margin: 0.75em; + overflow: visible; + vertical-align: middle; + } - div.page-number - { - color: #606060; - display: inline-block; - font-size: 40px; - height: 32px; - width: 32px; - overflow: visible; - } + div.page-number + { + color: #606060; + display: inline-block; + font-size: 40px; + height: 32px; + width: 32px; + overflow: visible; + } - div.result - { - display: inline-block; - margin: 0.75em; - overflow: visible; - vertical-align: top; - } + div.result + { + display: inline-block; + margin: 0.75em; + overflow: visible; + vertical-align: top; + } - div.result img - { - border-color: black; - border-width: 1px; - } + div.result img + { + border-color: black; + border-width: 1px; + } - div.search - { - padding: 0.75em; - } + div.search + { + padding: 0.75em; + } - div.search-small - { - clear: both; - float: right; - height: 0em; - overflow: visible; - text-align: right; - } + div.search-small + { + clear: both; + float: right; + height: 0em; + overflow: visible; + text-align: right; + } - div.toplists - { - padding: 0.75em; - } + div.toplists + { + padding: 0.75em; + } - div.tagcloud - { - background-color: #f0f0f0; - border-color: #c0c0c0; - border-style: solid; - border-width: 1px; - margin: 0.75em; - margin-left: 20%; - margin-right: 20%; - padding: 0.75em; - } + div.tagcloud + { + background-color: #f0f0f0; + border-color: #c0c0c0; + border-style: solid; + border-width: 1px; + margin: 0.75em; + margin-left: 20%; + margin-right: 20%; + padding: 0.75em; + } - div.video - { - display: inline-block; - margin-bottom: 0.5em; - } + div.video + { + display: inline-block; + margin-bottom: 0.5em; + } - div.videoccdata - { - margin: 0.75em; - } + div.videoccdata + { + margin: 0.75em; + } - div.videoccdata img - { - border-width: 0px; - margin-left: 0.5em; - margin-right: 0.5em; - margin-top: 0.5em; - } + div.videoccdata img + { + border-width: 0px; + margin-left: 0.5em; + margin-right: 0.5em; + margin-top: 0.5em; + } - div.video-metadata - { - display: inline-block; - line-height: 1.5em; - margin-left: 1.5em; - text-align: left; - vertical-align: top; - width: 256px; - } + div.video-metadata + { + display: inline-block; + line-height: 1.5em; + margin-left: 1.5em; + text-align: left; + vertical-align: top; + width: 256px; + } - div.videotitle - { - font-size: 1.5em; - margin-bottom: 0.5em; - } + div.videotitle + { + font-size: 1.5em; + margin-bottom: 0.5em; + } fieldset { - border-width: 0px; + border-width: 0px; } - img.logo-big - { - padding-bottom: 0.5em; - } + img.logo-big + { + padding-bottom: 0.5em; + } - img.openid-icon - { - padding-left: 0.2em; - vertical-align: text-top; - } + img.openid-icon + { + padding-left: 0.2em; + vertical-align: text-top; + } span.code { - font-family: monospace; - font-weight: normal; + font-family: monospace; + font-weight: normal; } span.heading { - font-size: 1.5em; + font-size: 1.5em; } span.instruction, span.protip { - color: #606060; + color: #606060; } span.protip:after { - content: " )"; + content: " )"; } span.protip:before { - content: "( "; + content: "( "; } table.metadata, table.metadata-upload { - border-width: 0px; - border-collapse: collapse; - width: 100%; + border-width: 0px; + border-collapse: collapse; + width: 100%; } - table.metadata td.metadata-content, - table.metadata td.metadata-title, - table.metadata-upload td.metadata-content - { - text-align: left; - width: 50%; - } + table.metadata td.metadata-content, + table.metadata td.metadata-title, + table.metadata-upload td.metadata-content + { + text-align: left; + width: 50%; + } - table.metadata td.metadata-title - { - width: 40%; - } + table.metadata td.metadata-title + { + width: 40%; + } - table.metadata-upload td.metadata-title - { - text-align: right; - width: 50%; - } + table.metadata-upload td.metadata-title + { + text-align: right; + width: 50%; + } td.metadata-title { - color: #606060; -} \ No newline at end of file + color: #606060; +} diff --git a/trunk/style/embedded.css b/trunk/style/embedded.css index 970ce1b..f5265a3 100644 --- a/trunk/style/embedded.css +++ b/trunk/style/embedded.css @@ -1,21 +1,21 @@ body { - font-family: sans-serif; - font-size: 8pt; - font-weight: bold; - overflow: visible; + font-family: sans-serif; + font-size: 8pt; + font-weight: bold; + overflow: visible; } div.watch-browserplugin, div.watch-cortadoapplet { - float: left; - text-align: left; - width: 50%; + float: left; + text-align: left; + width: 50%; } div.embedded-backlink { - float: right; - text-align: right; - width: 50%; -} \ No newline at end of file + float: right; + text-align: right; + width: 50%; +} diff --git a/trunk/tools/daemon.pl b/trunk/tools/daemon.pl index 4049621..8737ea0 100755 --- a/trunk/tools/daemon.pl +++ b/trunk/tools/daemon.pl @@ -21,20 +21,20 @@ $LOG = "$root/daemon.log"; #TODO: maybe keep file open the whole time ? sub appendlog { - if (open(FILE, ">>$LOG")) - { - print FILE scalar(localtime)." ".$$."\n"; - print "------------------------------------\n"; - print join("\n",@_)."\n"; - print "------------------------------------\n\n"; - close FILE; - } + if (open(FILE, ">>$LOG")) + { + print FILE scalar(localtime)." ".$$."\n"; + print "------------------------------------\n"; + print join("\n",@_)."\n"; + print "------------------------------------\n\n"; + close FILE; + } } sub interrupt { - appendlog(@_); - die; + appendlog(@_); + die; } $dbh = DBI->connect("DBI:mysql:$database:$dbhost", $dbuser, $dbpass) or interrupt "could not connect to db"; @@ -49,166 +49,166 @@ $dbh = DBI->connect("DBI:mysql:$database:$dbhost", $dbuser, $dbpass) or interrup while(1) { - #get fresh video id from db - my $sth = $dbh->prepare(qq{select id from uploaded where status = 0 limit 1}) or interrupt $dbh->errstr; - - $sth->execute() or interrupt $dbh->errstr; - my ($id) = $sth->fetchrow_array(); - $sth->finish() or interrupt $dbh->errstr; - - if($id) - { - $info = `export SDL_VIDEODRIVER="dummy"; ffplay -stats -an -vn -nodisp /tmp/$id 2>&1`; - - if($info =~ /ignoring/) - { - appendlog "id: $id", - "error: invalid stream", - "ffplay msg: $info"; - - #write status 2 to uploaded table - $dbh->do(qq{update uploaded set status = ? where id = ?}, undef, 2, $id) or interrupt $dbh->errstr; - unlink "/tmp/$id"; - } - elsif ($info =~ /I\/O error occured/) - { - appendlog "id: $id", - "error: file not found", - "ffplay msg: $info"; - - #write status 3 to uploaded table - $dbh->do(qq{update uploaded set status = ? where id = ?}, undef, 3, $id) or interrupt $dbh->errstr; - unlink "/tmp/$id"; - } - elsif ($info =~ /Unknown format/ or $info =~ /could not find codec parameters/) - { - appendlog "id: $id", - "error: file is of unknown format", - "ffplay msg: $info"; - - #write status 4 to uploaded table - $dbh->do(qq{update uploaded set status = ? where id = ?}, undef, 4, $id) or interrupt $dbh->errstr; - unlink "/tmp/$id"; - } - else - { - $sha = new Digest::SHA(256); - $sha->addfile("/tmp/$id"); - $sha = $sha->hexdigest; - - #check if this hash is already in database - my $sth = $dbh->prepare(qq{select id from videos where hash = ? limit 1}) or interrupt $dbh->errstr; - $sth->execute($sha) or interrupt $dbh->errstr; - my ($resultid) = $sth->fetchrow_array(); - $sth->finish() or interrupt $dbh->errstr; - - #if so, then video is a duplicate (alternatively ALL HAIL QUANTUM COMPUTING) - if($resultid) - { - appendlog "id: $id", - "error: video already uploaded: $resultid"; - - #write status 5 to uploaded table - $dbh->do(qq{update uploaded set status = ? where id = ?}, undef, 5, $id) or interrupt $dbh->errstr; - unlink "/tmp/$id"; - } - else - { - ($container, $duration) = $info =~ /Input \#0, (\w+),.+?\n.+?Duration: (\d{2}:\d{2}:\d{2}\.\d)/; - - #these two regexes have to be applied seperately because nobody knows which stream (audio or video) comes first - ($audio) = $info =~ /Audio: (\w+)/; - ($video, $width, $height, $fps) = $info =~ /Video: ([\w\d]+),.+?(\d+)x(\d+),.+?(\d+\.\d+) fps/; - - if(!$audio or !$video or !$duration) - { - appendlog "id: $id", - "error: error: stream is missing or video is corrupt", - "audio: $audio", - "video: $video", - "duration: $duration", - "ffplay msg: $info"; - - #write status 2 to uploaded table - $dbh->do(qq{update uploaded set status = ? where id = ?}, undef, 2, $id) or interrupt $dbh->errstr; - unlink "/tmp/$id"; - } - else - { - $filesize = -s "/tmp/$id"; - - #convert hh:mm:ss.s duration to full seconds - thanks perl for making this so damn easy! - #don't want to know how this would look in python or php... hell I don't even have to create extra variables! - $duration =~ /^(\d{2}):(\d{2}):(\d{2})\.(\d)$/; - $duration = int($1*3600 + $2*60 + $3 + $4/10 + .5); - - #create thumbnail - $thumbnailsec = int($duration/3 + .5); - - #the width/height calculation could of course be much shorter but less readable then - #all thumbs have equal height - $tnmaxheight = 120; - $tnheight = $tnmaxheight; - $tnwidth = int($tnheight*($width/$height)/2 + .5)*2; - - system "ffmpeg -i /tmp/$id -vcodec mjpeg -vframes 1 -an -f rawvideo -ss $thumbnailsec -s ".$tnwidth."x$tnheight $root/video-stills/$id"; - - $vmaxheight = 640; - - #check if the upload already is in the right format and smaller/equal max-width/height - if ($container eq 'ogg' and $video eq 'theora' and $audio eq 'vorbis' and $height <= $vmaxheight) - { - appendlog $id, "file already is ogg-theora/vorbis"; - - #add video to videos table - $dbh->do(qq{insert into videos select id, title, description, userid, timestamp, creator, - subject, source, language, coverage, rights, license, ?, ?, ?, ?, ?, ?, 0, 0 - from uploaded where id = ?}, undef, $filesize, $duration, $width, - $height, $fps, $sha, $id) or interrupt $dbh->errstr; - - #move video - move "/tmp/$id", "$root/videos/$id"; - } - else #encode video - { - #video height is either ther maximum video height - #or when the original is smaller than that the original height - #check for multiple by 8 - $vheight = $vmaxheight <= $height ? $vmaxheight : int($height/8 + .5)*8; - $vwidth = int($vheight*($width/$height)/8 + .5)*8; - - $abitrate = 64; - $vbitrate = int($filesize*8) / $duration + .5) - $abitrate; - - #TODO: add metadata information - system "ffmpeg2theora --optimize --videobitrate $vbitrate --audiobitrate $abitrate --sharpness 0 --width $vwidth --height $vheight --output $root/videos/$id /tmp/$id"; - - appendlog $id, $audio, $video, $vwidth, $vheight, $fps, $duration, $sha; - - $filesize = -s "$root/videos/$id"; - - #add video to videos table - $dbh->do(qq{insert into videos select id, title, description, userid, timestamp, creator, - subject, source, language, coverage, rights, license, ?, ?, ?, ?, ?, ?, 0, 0 - from uploaded where id = ?}, undef, $filesize, $duration, $vwidth, - $vheight, $fps, $sha, $id) or interrupt $dbh->errstr; - - #delete temp file - unlink "/tmp/$id"; - } - - #create torrent file - - - #delete from uploaded table - $dbh->do(qq{delete from uploaded where id = ?}, undef, $id) or interrupt $dbh->errstr; - } - } - } - } - else - { - TODO: maybe make this event-driven by using the kernels has-this-file-changed-interface ? - sleep 10; - } + #get fresh video id from db + my $sth = $dbh->prepare(qq{select id from uploaded where status = 0 limit 1}) or interrupt $dbh->errstr; + + $sth->execute() or interrupt $dbh->errstr; + my ($id) = $sth->fetchrow_array(); + $sth->finish() or interrupt $dbh->errstr; + + if($id) + { + $info = `export SDL_VIDEODRIVER="dummy"; ffplay -stats -an -vn -nodisp /tmp/$id 2>&1`; + + if($info =~ /ignoring/) + { + appendlog "id: $id", + "error: invalid stream", + "ffplay msg: $info"; + + #write status 2 to uploaded table + $dbh->do(qq{update uploaded set status = ? where id = ?}, undef, 2, $id) or interrupt $dbh->errstr; + unlink "/tmp/$id"; + } + elsif ($info =~ /I\/O error occured/) + { + appendlog "id: $id", + "error: file not found", + "ffplay msg: $info"; + + #write status 3 to uploaded table + $dbh->do(qq{update uploaded set status = ? where id = ?}, undef, 3, $id) or interrupt $dbh->errstr; + unlink "/tmp/$id"; + } + elsif ($info =~ /Unknown format/ or $info =~ /could not find codec parameters/) + { + appendlog "id: $id", + "error: file is of unknown format", + "ffplay msg: $info"; + + #write status 4 to uploaded table + $dbh->do(qq{update uploaded set status = ? where id = ?}, undef, 4, $id) or interrupt $dbh->errstr; + unlink "/tmp/$id"; + } + else + { + $sha = new Digest::SHA(256); + $sha->addfile("/tmp/$id"); + $sha = $sha->hexdigest; + + #check if this hash is already in database + my $sth = $dbh->prepare(qq{select id from videos where hash = ? limit 1}) or interrupt $dbh->errstr; + $sth->execute($sha) or interrupt $dbh->errstr; + my ($resultid) = $sth->fetchrow_array(); + $sth->finish() or interrupt $dbh->errstr; + + #if so, then video is a duplicate (alternatively ALL HAIL QUANTUM COMPUTING) + if($resultid) + { + appendlog "id: $id", + "error: video already uploaded: $resultid"; + + #write status 5 to uploaded table + $dbh->do(qq{update uploaded set status = ? where id = ?}, undef, 5, $id) or interrupt $dbh->errstr; + unlink "/tmp/$id"; + } + else + { + ($container, $duration) = $info =~ /Input \#0, (\w+),.+?\n.+?Duration: (\d{2}:\d{2}:\d{2}\.\d)/; + + #these two regexes have to be applied seperately because nobody knows which stream (audio or video) comes first + ($audio) = $info =~ /Audio: (\w+)/; + ($video, $width, $height, $fps) = $info =~ /Video: ([\w\d]+),.+?(\d+)x(\d+),.+?(\d+\.\d+) fps/; + + if(!$audio or !$video or !$duration) + { + appendlog "id: $id", + "error: error: stream is missing or video is corrupt", + "audio: $audio", + "video: $video", + "duration: $duration", + "ffplay msg: $info"; + + #write status 2 to uploaded table + $dbh->do(qq{update uploaded set status = ? where id = ?}, undef, 2, $id) or interrupt $dbh->errstr; + unlink "/tmp/$id"; + } + else + { + $filesize = -s "/tmp/$id"; + + #convert hh:mm:ss.s duration to full seconds - thanks perl for making this so damn easy! + #don't want to know how this would look in python or php... hell I don't even have to create extra variables! + $duration =~ /^(\d{2}):(\d{2}):(\d{2})\.(\d)$/; + $duration = int($1*3600 + $2*60 + $3 + $4/10 + .5); + + #create thumbnail + $thumbnailsec = int($duration/3 + .5); + + #the width/height calculation could of course be much shorter but less readable then + #all thumbs have equal height + $tnmaxheight = 120; + $tnheight = $tnmaxheight; + $tnwidth = int($tnheight*($width/$height)/2 + .5)*2; + + system "ffmpeg -i /tmp/$id -vcodec mjpeg -vframes 1 -an -f rawvideo -ss $thumbnailsec -s ".$tnwidth."x$tnheight $root/video-stills/$id"; + + $vmaxheight = 640; + + #check if the upload already is in the right format and smaller/equal max-width/height + if ($container eq 'ogg' and $video eq 'theora' and $audio eq 'vorbis' and $height <= $vmaxheight) + { + appendlog $id, "file already is ogg-theora/vorbis"; + + #add video to videos table + $dbh->do(qq{insert into videos select id, title, description, userid, timestamp, creator, + subject, source, language, coverage, rights, license, ?, ?, ?, ?, ?, ?, 0, 0 + from uploaded where id = ?}, undef, $filesize, $duration, $width, + $height, $fps, $sha, $id) or interrupt $dbh->errstr; + + #move video + move "/tmp/$id", "$root/videos/$id"; + } + else #encode video + { + #video height is either ther maximum video height + #or when the original is smaller than that the original height + #check for multiple by 8 + $vheight = $vmaxheight <= $height ? $vmaxheight : int($height/8 + .5)*8; + $vwidth = int($vheight*($width/$height)/8 + .5)*8; + + $abitrate = 64; + $vbitrate = int($filesize*8) / $duration + .5) - $abitrate; + + #TODO: add metadata information + system "ffmpeg2theora --optimize --videobitrate $vbitrate --audiobitrate $abitrate --sharpness 0 --width $vwidth --height $vheight --output $root/videos/$id /tmp/$id"; + + appendlog $id, $audio, $video, $vwidth, $vheight, $fps, $duration, $sha; + + $filesize = -s "$root/videos/$id"; + + #add video to videos table + $dbh->do(qq{insert into videos select id, title, description, userid, timestamp, creator, + subject, source, language, coverage, rights, license, ?, ?, ?, ?, ?, ?, 0, 0 + from uploaded where id = ?}, undef, $filesize, $duration, $vwidth, + $vheight, $fps, $sha, $id) or interrupt $dbh->errstr; + + #delete temp file + unlink "/tmp/$id"; + } + + #create torrent file + + + #delete from uploaded table + $dbh->do(qq{delete from uploaded where id = ?}, undef, $id) or interrupt $dbh->errstr; + } + } + } + } + else + { + TODO: maybe make this event-driven by using the kernels has-this-file-changed-interface ? + sleep 10; + } } diff --git a/trunk/tools/tagcloud.pl b/trunk/tools/tagcloud.pl index 3f6b405..9001e78 100755 --- a/trunk/tools/tagcloud.pl +++ b/trunk/tools/tagcloud.pl @@ -13,15 +13,15 @@ $sth = $dbh->prepare("select subject from videos"); $sth->execute(); while(($subject) = $sth->fetchrow_array()) { - @subject = split(' ', $subject); - foreach my $val (@subject) - { - $val =~ s/^\s*(.*?)\s*$/$1/; - if(length($val) >= 4) - { - %hash->{$val}++; - } - } + @subject = split(' ', $subject); + foreach my $val (@subject) + { + $val =~ s/^\s*(.*?)\s*$/$1/; + if(length($val) >= 4) + { + %hash->{$val}++; + } + } } $sth->finish(); @@ -31,5 +31,5 @@ $dbh->do("delete from tagcloud"); $sth = $dbh->prepare("insert into tagcloud (text, count) values (?, ?)"); for($i=0;$i<20 and $i<=$#sorted;$i++) { - $sth->execute( $sorted[$i], %hash->{$sorted[$i]} ); + $sth->execute( $sorted[$i], %hash->{$sorted[$i]} ); } diff --git a/trunk/tools/yolanda-upload.pl b/trunk/tools/yolanda-upload.pl index a61f264..bbafb07 100755 --- a/trunk/tools/yolanda-upload.pl +++ b/trunk/tools/yolanda-upload.pl @@ -40,7 +40,7 @@ getopts('u:p:f:t:d:x:c:s:l:v:', \%opts); unless (defined $opts{u}) { unless (length USER) { preamble(); - print "Username was neither defined nor passed as an argument\n"; + print "Username was neither defined nor passed as an argument\n"; print "Use -u switch to specify the username\n"; print "Example: -u joe_random\n"; exit 1; @@ -97,8 +97,8 @@ print "Getting sid cookie...\n"; $response = $ua->request(GET $url); unless($response->is_success) { - die "Failed opening $url: ", - $response->status_line; + die "Failed opening $url: ", + $response->status_line; } print "Logging in to $url/login.pl...\n"; @@ -106,33 +106,33 @@ print "Logging in to $url/login.pl...\n"; $response = $ua->request(POST "$url/login.pl", "Content_Type" => "form-data", "Content" => [action => login, user => test, pass => test]); unless($response->is_success) { - die "Failed logging in: ", - $response->status_line; + die "Failed logging in: ", + $response->status_line; } unless($response->content =~ /action=logout/) { - die "Failed logging in: username/password do not match"; + die "Failed logging in: username/password do not match"; } print "Uploading $opts{f} to $url/uploader.pl...\n"; # DONT PRINT THIS - UNIX PHILOSPHY IS: IF IT WORKS DONT DISPLAY SHIT ! ( maybe add a -v switch ) $response = $ua->request(POST "$url/uploader.pl", - "Content_Type" => "multipart/form-data", - "Content" => [ - file => [$opts{f}], - "DC.Title" => $opts{t}, - "DC.Description" => $opts{d}, - "DC.Subject" => $opts{x}, - "DC.Creator" => $opts{c} ? $opts{c} : "", - "DC.Source" => $opts{s} ? $opts{s} : "", - "DC.Language" => $opts{l} ? $opts{l} : "", - "DC.Coverage" => $opts{v} ? $opts{v} : "", - ] + "Content_Type" => "multipart/form-data", + "Content" => [ + file => [$opts{f}], + "DC.Title" => $opts{t}, + "DC.Description" => $opts{d}, + "DC.Subject" => $opts{x}, + "DC.Creator" => $opts{c} ? $opts{c} : "", + "DC.Source" => $opts{s} ? $opts{s} : "", + "DC.Language" => $opts{l} ? $opts{l} : "", + "DC.Coverage" => $opts{v} ? $opts{v} : "", + ] ); unless($response->is_success) { - die "Failed uploading: ", - $response->status_line; + die "Failed uploading: ", + $response->status_line; } print "Done!\n"; # DONT PRINT THIS - UNIX PHILOSPHY IS: IF IT WORKS DONT DISPLAY SHIT ! ( maybe add a -v switch )