| -rw-r--r-- | java/org/encours/tools/VideoMaker.java | 61 | ||||
| -rwxr-xr-x | tools/make_video_page.pl | 162 |
2 files changed, 192 insertions, 31 deletions
diff --git a/java/org/encours/tools/VideoMaker.java b/java/org/encours/tools/VideoMaker.java index dd24182..82ad7c7 100644 --- a/java/org/encours/tools/VideoMaker.java +++ b/java/org/encours/tools/VideoMaker.java @@ -126,6 +126,7 @@ public class VideoMaker { int xpos = (int)(laserState.x * currentImage.getWidth() - dotSize*0.5f); int ypos = (int)(laserState.y * currentImage.getHeight() - dotSize*0.5f); Graphics2D g = currentImage.createGraphics(); + g.clipRect(0,0,currentImage.getWidth(),currentImage.getHeight()); g.setColor(laserColor[numLaser % laserColor.length]); g.fillOval(xpos,ypos,dotSize,dotSize); } @@ -155,22 +156,47 @@ public class VideoMaker { ffmpegCommand = "ffmpeg"; if (pass>0) ffmpegCommand += " -pass "+pass; - ffmpegCommand += " -v 1 -y -f image2pipe -vcodec ppm -r "+inputFrameRate+":1 -i -"; + ffmpegCommand += " -v 1 -y -f image2pipe -s 1024x768 -vcodec ppm -r "+inputFrameRate+":1 -i -"; if (pass!=1) ffmpegCommand += " -i "+ args[1]; // FLV settings if (filename.toLowerCase().endsWith("flv")) { if (pass!=1) ffmpegCommand += " -acodec libmp3lame -ab 32k -ar 22050"; - ffmpegCommand += " -r 10 -s 512x384 -vcodec flv -g 200 -qscale 5"; +// ffmpegCommand += " -r 10 -s 512x384 -vcodec flv -g 200 -qscale 5"; + + ffmpegCommand += " -r 10 -s 640x480 -vcodec flv -g 200 -qscale 5"; + // Vorbis/Theora by default } else { - if (pass!=1) ffmpegCommand += " -acodec libvorbis -ab 16k -ar 16000"; - ffmpegCommand += " -r 10 -s 640x480 -vcodec libtheora -g 50 -qscale 8"; -// ffmpegCommand += " -r 10 -s 512x384 -vcodec libtheora -g 30 -qscale 7"; +// OKÂ GOOD +// if (pass!=1) ffmpegCommand += " -acodec libvorbis -ab 32k -ar 16000"; + + +// Test for flac/png/avi file + if (pass!=1) ffmpegCommand += " -acodec flac -ar 16000"; + ffmpegCommand += " -r 10 -s 640x480 -vcodec png -g 128 -qscale 6"; + +// OK if libtheora present +// ffmpegCommand += " -r 10 -s 640x480 -vcodec libtheora -g 50 -qscale 8"; +// smaller files, ok in mplayer but not in firefox +// ffmpegCommand += " -r 10 -s 640x480 -vcodec libtheora -g 128 -qscale 6"; +// OLD ffmpegCommand += " -r 10 -s 512x384 -vcodec libtheora -g 30 -qscale 7"; } if (pass==1) ffmpegCommand += " -f rawvideo -y /dev/null"; else ffmpegCommand += " "+ filename; + + + // hack + if (filename.toLowerCase().endsWith("ogv")) { + +// ffmpegCommand = "ffmpeg2theora --optimize -x 640 -y 480 -f image2pipe --inputfps 10 -v 6 -K 128 -o " + filename + " -"; + +//ffmpegCommand = "ffmpeg2theora --inputfps 10 -f image2pipe -o " + filename + " -"; + } + + + try { System.out.println("Executing ffmpeg: "+ ffmpegCommand); ffmpeg = Runtime.getRuntime().exec(ffmpegCommand); @@ -207,7 +233,7 @@ public class VideoMaker { } }.start(); - + try { while (true) { int tstamp = recFile.getInt(); @@ -300,14 +326,14 @@ public class VideoMaker { String basename = new File(args[2]).getName(); String filename = null; - System.out.println("Generating the ogg/theora replay..."); + System.out.println("Generating the png/avi replay..."); try { - filename = new File(args[2],basename+".ogv").getCanonicalPath(); + filename = new File(args[2],basename+".avi").getCanonicalPath(); } catch (IOException e) { e.printStackTrace(); } - vm.process(args,1,filename); + vm.process(args,0,filename); while (true) { try { Thread.sleep(5000); @@ -316,8 +342,17 @@ public class VideoMaker { } break; } - - vm.process(args,2,filename); +return; +/* + + System.out.println("Generating the ogg/theora replay..."); + try { + filename = new File(args[2],basename+".ogv").getCanonicalPath(); + } catch (IOException e) { + e.printStackTrace(); + } + + vm.process(args,0,filename); while (true) { try { Thread.sleep(5000); @@ -377,7 +412,7 @@ public class VideoMaker { } catch (InterruptedException e) { e.printStackTrace(); } - - } +*/ + } } diff --git a/tools/make_video_page.pl b/tools/make_video_page.pl index d4d98f4..93d48f2 100755 --- a/tools/make_video_page.pl +++ b/tools/make_video_page.pl @@ -1,7 +1,12 @@ #!/usr/bin/perl -if ($#ARGV!=0) { - print "Argument needed: one directory containing ogv and/or flv videos, where to generate the replay.html page\n"; +if ($#ARGV<0) { +print <<HELPEND; +Arguments needed: +- Required: One directory containing ogv and/or flv videos, where to generate the replay.html page +- Optional: A record file containing events. If there is a ".rec" file in the target directory then it will be used by default. If no file is found the replay page will not contain an HTML5 index for the video. +- Optional: A text file containing the titles for the index. If the directory contains a file 'titles.txt' then these titles will be used by default. If no file is found then the titles will be extracted from the PDF, and a 'titles.txt' will be generated. Edit this file and re-run the command if needed. +HELPEND exit(1); } @@ -16,8 +21,65 @@ $toolsdir =~ s,/?[^/]*/*$,,; system("cp $toolsdir/flvplayer/player_flv_maxi.swf $dir/flvplayer.swf"); system("cp $toolsdir/cortado/cortado-ovt-stripped-0.5.1.jar $dir/cortado.jar"); +# Process events +if ($#ARGV>0) { + $eventfile = $ARGV[1]; + open(EVENTS,"<$eventfile"); + @events=<EVENTS>; + close(EVENTS); + if ($#events<0) { + print "Invalid event file: $ARGV[1]\n"; + exit(1); + } + @titles=(); + # load or generate the titles list + if ($#ARGV>1) { + $titlefile = $ARGV[2]; + open(TITLE,"<$titlefile"); + @titles=<TITLE>; + close(TITLE); + } else { + open(TITLE,"<$dir/titles.txt"); + @titles=<TITLE>; + close(TITLE); + } + if ($#titles<0) { + `pdfinfo $dir/slides.pdf|grep Pages` =~ /Pages: *(.*)/; + $numPages=$1; + for $p (1..$numPages) { + @doctext=`pdftotext -f $p -l $p $dir/slides.pdf -`; + # would be nice here: recognize a real title from garbage + push @titles, $doctext[0]; + } + open(TITLE,">$dir/titles.txt"); + print TITLE @titles; + close(TITLE); + } + # there may still be an error, ex: no slides.pdf file + if ($#titles<0) { + print "Titles could not be loaded or generated\n"; + exit(1); + } + # run through the events list for page change timings + %timings=(1=>0); + for $ev (@events) { + @evparam=split(" ", $ev); + if ($evparam[1]==10) { + $pagenum=$evparam[2]; + # ignore going back, take only the first time a page is loaded + if (! exists $timings{$pagenum}) { + # convert to seconds + $timings{$pagenum}=$evparam[0] / 1000; + } + } + } +} + chdir($dir); + + + for $fname (glob("*.flv")) { $fname =~ s/\.flv//; $dirfiles{$fname} = $fname; @@ -49,42 +111,106 @@ if ($l =~ /Content-Duration: ([0-9]+):([0-9][0-9]):([0-9][0-9])\.([0-9][0-9][0-9 open REPLAY, ">replay.html"; -print REPLAY <<ENDOFHTML1; +print REPLAY <<ENDOFHTML; <html> <head> <title>Encours presentation video replay</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> +ENDOFHTML +if ($#titles>=0) { +print REPLAY <<ENDOFHTML; +<style type="text/css"> +<!-- +ul {list-style:none inside; padding-left:1em;} +--> +</style> +<script type="text/javascript"> +function seekvideo(id,time) { + var needflv=false; + try { + if (document.getElementById(id)!=null) { + document.getElementById(id).currentTime = time; + document.getElementById(id).play(); + } else needflv=true; + } catch (err) { + needflv=true; + } + if (needflv) try { + if (document.getElementById(id+"flv")!=null) { + document.getElementById(id+"flv").SetVariable("player:jsSetPosition", time); + document.getElementById(id+"flv").SetVariable("player:jsPlay", ""); + } + } catch (err) { + } +} +</script> +ENDOFHTML +} +print REPLAY <<ENDOFHTML; </head> <body> -ENDOFHTML1 +ENDOFHTML if (-e $ogvfile) { -print REPLAY <<ENDOFHTML2; -<video src="$ogvfile" controls> +print REPLAY <<ENDOFHTML; +<table><tr><td style="vertical-align:top;padding:1em"> +<video id="replay" src="$ogvfile" controls> +ENDOFHTML +} + +if (-e $flvfile) { +print REPLAY <<ENDOFHTML; +<object id="replayflv" type="application/x-shockwave-flash" data="flvplayer.swf" width="640" height="480"> + <param name="movie" value="flvplayer.swf" /> + <param name="FlashVars" value="flv=$flvfile&autoload=1" /> +ENDOFHTML +} + +if (-e $ogvfile) { +print REPLAY <<ENDOFHTML; <applet code="com.fluendo.player.Cortado.class" archive="cortado.jar" width="640" height="480"> <param name="url" value="$ogvfile"/>$lenparam <param name="framerate" value="10"/> <param name="autoPlay" value="false"/> -ENDOFHTML2 +You need either an HTML5 compliant browser, flash, or java installed, to see the video. +</applet> +ENDOFHTML +} elsif (-e $flvfile) { +print REPLAY "You need flash installed to see the video.\n"; } if (-e $flvfile) { -print REPLAY <<ENDOFHTML3; -<object type="application/x-shockwave-flash" data="flvplayer.swf" width="512" height="384"> - <param name="movie" value="flvplayer.swf" /> - <param name="FlashVars" value="flv=$flvfile&autoload=1" /> +print REPLAY <<ENDOFHTML; </object> -ENDOFHTML3 +ENDOFHTML } + if (-e $ogvfile) { -print REPLAY <<ENDOFHTML4; -</applet> +print REPLAY <<ENDOFHTML; </video> -<p><a href="$ogvfile">Download the video for offline view</a></p> -ENDOFHTML4 +<p style="margin-top:2em"><a href="$ogvfile">Download the video for offline view</a></p> +ENDOFHTML +if (-r "slides.pdf") { +print REPLAY "<p><a href=\"slides.pdf\">Download the slides as PDF</a></p>\n"; +} +print REPLAY <<ENDOFHTML; +</td> +<td> +ENDOFHTML +if ($#titles>=0) { + print REPLAY "<div style=\"border-left:1px solid black\"><ul>"; + for $page ( sort { $a <=> $b } keys %timings ) + { + print REPLAY "<li><a href=\"javascript:seekvideo('replay',$timings{$page})\">$page: $titles[$page-1]</a></li>\n"; + } + print REPLAY "</ul></div>"; +} +print REPLAY <<ENDOFHTML; +</td></tr></table> +ENDOFHTML } elsif (-e $flvfile) { print REPLAY "<p><a href=\"$flvfile\">Download the video for offline view</a></p>" } -print REPLAY <<ENDOFHTML5; +print REPLAY <<ENDOFHTML; </body> <html> -ENDOFHTML5 +ENDOFHTML |
