Extension talk:VideoSectionLink

From Organic Design wiki

See also

Some quite developed projects around this idea, --Rob 21:28, 20 November 2008 (NZDT)

Dev notes

The Unknownaction function is not being called by the hook, the string I have constructed is being returned as wikitext on the page, but print_r are not printing.--Jack 15:14, 18 November 2008 (NZDT)

I take that back, it is being called. I'll have a go at the $wgRequest now--Jack 15:20, 18 November 2008 (NZDT)
Actually I have no idea whether it is being called or not--Jack 15:28, 18 November 2008 (NZDT)


The page where the magic word is used is displaying the string that I constructed, which is

http://localhost/http://www.jack.co.nz?action=videosection&param2=350&param3=270

I expect I have to give the page some sort of title but its only function is to embed a movie, ie not be editable or anything.--Jack 09:25, 11 November 2008 (NZDT)

Actually if I put the movie name in the title like
http://localhost/test.mpeg?action=videosection&param2=350&param3=270
I can extract it later.--Jack 09:36, 11 November 2008 (NZDT)
I don't expect I can just pass php variables to the shell anyway, the command inside the backticks surely has to be a string--Jack 09:59, 11 November 2008 (NZDT)

Still reading about parser functions.


I've just added a couple of traces and the browser prints those fine. In my wikitext mainpage locally I have

{{videosectionlink:broom}}

and that prints the traces and does nothing.


If instead I put into the article

{{#videosectionlink:broom}}

i get the traces then

Fatal error: Call to a member function getPrefixedDBkey() on a non-object in C:\www\wiki4\includes\parser\Preprocessor_DOM.php on line 994


Then by commenting out the regexes and adding a trace as shown, it compiles and prints "brush", which is correct, and means the function is being called.


I think there may be a property of the object VideoSectionLink which contains the string "broom". Here is the output:

LGM: Array ( [0] => en [1] => videosectionlink ) VSL instance: VideoSectionLink Object ( ) brush 

--Jack 13:09, 9 November 2008 (NZDT)

I'd recommend going back to the initial template again and deleting the tag out again bit by bit, you must have removed something you shouldn't have because the extension is fully functional before being modified from the template. Also, you should use camelCase for all functions, the current code has the function magicVideosectionlink which should be magicVideoSectionLink. --nad 13:04, 9 November 2008 (NZDT)
Also the braces syntax for categorisation and php syntax need to be inside the php comment section otherwise they make the code unexecutable --nad 13:07, 9 November 2008 (NZDT)
Actually don't go back to the template - its a weird problem to do with the $args variable being put into the output string, just remove that - I don't know why it causes an error though when its just a string... ??? --nad 13:18, 9 November 2008 (NZDT)
If I read you right, what I have done is changed the line
$text = "=== Magic $egVideoSectionLinkMagic(): ===\n$args";
into
$text = "=== Magic $egVideoSectionLinkMagic(): ===\n";
same fatal error. The wikitext on the main page that is causing this error is
{{#videosectionlink:http://www.jack.co.nz/}}
but same preparser error for
{{#videosectionlink:foo}}


Could be a version issue. Here is a talk page about it, noting issue with versions 1.12 and 1.13:


http://semeb.com/dpldemo/index.php?title=Issue:Call_to_a_member_function_getPrefixedDBkey()_on_a_non-object --Jack 14:11, 9 November 2008 (NZDT)

That article is specific to DPL, just forget about it, make the parser function the way you want it and see if you still get the problem. --nad 14:35, 9 November 2008 (NZDT)
Just commenting out the magic words expansion for now, I do at least have the function returning its parameters back to the page: using the magic word with two pipes produces this on the page
param1 is http://www.jack.co.nz and param2 is 350 and param3 is 350 

--Jack 09:56, 10 November 2008 (NZDT)

I now need to cause the shell to execute ffmpeg with its parameters from the parser function, I don't know how to do that ...

--Jack 13:14, 10 November 2008 (NZDT)

Backticks seem to have solved the parser error --Jack 15:39, 10 November 2008 (NZDT)

Yo thats got started pretty quick :-) but best to to set the tag name to something shorter like videosection --nad 21:26, 31 October 2008 (NZDT)

What I want to do now is to just list all the sub-parts of this extension so I expect they are all contained in the comments below, if there is any missed I expect I will find out soon enough --Jack 21:40, 31 October 2008 (NZDT)
may as well dump the tag stuff since we only need the parser-function for this

--nad 22:03, 31 October 2008 (NZDT)

I note that the add tab in code snippets mentions adding a processing function to the UnknownAction hook but I don't see one --Jack 15:12, 3 November 2008 (NZDT)

Adding tabs is a different thing again, many tabs will not be an action - like the email article tab which goes to a special page. You don't really need any example, just add a callback to $wgHooks for UnknownAction. You can see from the MW docs on the hook that it has two parameters, the action being requested and the article, so just check if the action is your one, and if so, do your print_r or whatever. --nad 16:13, 3 November 2008 (NZDT)

Notes from 11 Nov discussion

  • Specifying methods in PHP callback functions: They can be a string of a global function name or an array of two elements, an object and a method name string (there are also more ways of specifying callbacks since PHP 5.2.3, see php.net/calback.
  • MediaWiki has an additional convention concerning callbacks which allows just an object with no function or method name string. In this case MediaWiki will assign a default method name of the same name as the hook it applies to preceded by "on". See [[MW:Manual:$wgHooks}} (I had to add the last case - it wasn't documented!)
  • You want shellexec() instead of the backtick operator, it's identical but takes a normal string parameter for the command and returns any standard out generated by the command.
  • The shellexecute will return either nothing or an error string/number, the generated movie will be written to the output file specified in the command (which should be under $wgUploadDirectory so it can definitely create files and write to them by making no assumptions about the local environment).
  • The link generated by the parser-function doesn't need to go to any specific wiki page, but does need to execute the script, you could use $wgServer, $wgScript etc, or another way is to use the current title object to generate an url like this: $wgTitle->getLocalURL('action=foo&bar=baz')

Parser function

We need a parser function so that links can be made using syntax such as the following:

{{#videosection:http://foo.bar/baz.avi|01:25:31|01:25:50}}

This would generate a link which when clicked downloads the specified segment of content from the specified video resource. Of course such a resource doesn't exist though, so the link is actually back to the wiki with action=videosection in the query string which will prompt the extension to generate the video section and return it to the client. The other parameters supplied in the parser-function should also be added to the query-string of the link.

Later we may add more parameters such as format and maybe embed - although embedding may be able to be achieved by using the existing video embedding extension with a VideoSectionLink URL as its source parameter.

Unknown action hook

The UnknownAction hook is used for executing code in response to new actions specified in the query string. An example of it's use is the PdfBook extension, it defines a callback method in its class called onUnknownAction and registers it with the hook in the classes' constructor.

This hook must construct an ffmpeg shell command from the query-string parameters and execute it, then pass the resulting binary or file back to the client. To pass the video data back to the client in such a way as to make it bring up the download dialog, use the following snippet. <php>

  1. First disable MediaWiki's output and set headers so the client knows this is a video for download

$wgOut->disable(); header("Content-Type: video/mpeg"); header("Content-Disposition: attachment; filename=\"$name.mpeg\"");

  1. Use this if sending string content to client

print $content;

  1. or use this if sending content of a file back to the client

readfile($file); </php>

Caching (later)

Whenever a new clip is generated, it should be stored in the wiki's tmp directory (which is where it also stores cached math equations and resized images. Here's a snippet of code taken from Extension:Flashlets.php which is doing a similar task. It's creating a binary file of compiled actionscript which has a filename that's unique to the actionscript so that different actionscript produces a different filename. VideoSectionLink would create cache files a similar way except that the unique names should be generated from the shell command string instead, and the command being executed to generate the content is ffmpeg or similar instead of the mtasc compiler. <php>

  1. create swf filename unique to the actionscript content and parameters

$swf = md5("$actionscript$ver$width$height$fps"); $file = "$wgFlashletsDirectory/$swf"; $path = "$wgFlashletsPath/$swf.swf";

  1. Compile the SWF if it doesn't already exist

if (!file_exists("$file.swf")) {

# Write the actionscript to a file for MTASC to compile from if ($handle = fopen("$file.as", 'w+')) { fwrite($handle,$actionscript); fclose($handle); $cont = $this->container; $sh = "$wgFlashletsMTASC -cp $wgFlashletsCP -swf $cont -out $file.swf -main -version $ver -header $width:$height:$fps $file.as 2>&1"; $html = shell_exec($sh); unlink("$file.as"); } else $html = "Could not open '$file.as' for writing!"; } </php>

Special page (later)

Later it could be good to have a special page which allows simple navigation of the video content to determine the exact start and finish times, and also as a means of creating a repository of video slices which could be then referred to by other sites that don't have the ability to refer to sections of video content.

ffmpeg

Use Case

  • Article Writer to be able to display a pre-selected part of a nominated video by writing a simple magic word such as:
{{#videosection:http://foo.bar/baz.avi|01:25:31|01:25:50}}
  • Viewer to be able to click on an apparently normal link. Perhaps to view it in a window on the same page, or as a Javascript popup.
  • Video can be hosted elsewhere on the Web or on the local system.
  • Range of video formats to be as complete as possible.

Code Needed

  • Create skeleton extension from template - done
  • Set up videosection as an action
  • Construct query string leading back to to the wiki, adding other parameters supplied in the parser-function i.e. start and finish times
  • Define a callback method onUnknownAction
  • Register the callback method with the hook in the constructor
  • Hook constructs an ffmpeg shell command from the query-string parameters and executes it

Parser-function being executed?

It was getting to hard to track the conversation with it in the middle of the doc, so starting a new section. Re current problems, just take things a step at a time - if you say you don't know whether or not its being called, then start printing some output at different points in the code to determine what's being executed and what's not. Remember to do ctrl+shift+refresh to reload the page properly. --nad 17:59, 18 November 2008 (NZDT)

Returning & embedding FLV's

The following has been tested and returns a segment from an arbitrary video as an flv

ffmpeg -i "/home/nad/Videos/Zeitgeist Addendum.avi" -ss 00:10:10 -t 00:00:05 -ar 22050 /home/nad/Desktop/foo.flv

The flash video embed extension generates the following embedding code:

<object width="425" height="350">
    <param name="movie" value="http://www.youtube.com/v/W4jXAaEMp2M"></param>
    <param name="wmode" value="transparent"></param>
    <embed src="http://www.youtube.com/v/W4jXAaEMp2M" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350">
    </embed>
</object>
I have constructed what looks like a proper HTML string but clearly returning it as an array is not going to work as it did with the parser function. All other desired functionality is present and tested --Jack 09:49, 23 November 2008 (NZDT)
Actually the correct way of doing it appears to be reproducing the functionality of the unknownaction function within the parser function if the embed flag is switched on, the code I have posted cannot work --Jack 10:16, 23 November 2008 (NZDT)
The parser function is now correctly returning the following HTML when the embed parameter is used:
<object width="425" height="350">
<param name="movie" value="/var/lib/mediawiki/images/b13a67095fe8ddcae949690af7bbaf5b.flv"></param><param name="wmode" value="transparent"></param>
<embed src="/var/lib/mediawiki/images/b13a67095fe8ddcae949690af7bbaf5b.flv" 
type="application/x-shockwave-flash" wmode="transparent" width="425" height="350">
</embed>
</object>

When the page is viewed there is an empty swf in a player of the correct size, so clearly its having some trouble finding the swf to display. I may have to use or adapt an embedding extension --Jack 11:51, 23 November 2008 (NZDT)

I think you need to change the src param to be in web space not local file system space. Try it with /images/b13a67095fe8ddcae949690af7bbaf5b.flv. Also i'm not sure if the flv will play on it's own, you might need a swf player like jwplayer. --Rob 12:46, 23 November 2008 (NZDT)
It seems that if you have a recent version of ffmpeg you can convert directly to swf and embed this - no need for a separate player (unless you want pause, rewind etc) --Rob 12:57, 23 November 2008 (NZDT)
I have the newest ffmpeg and it won't return a swf. I'm happy at the mo because my original intended functionality (create a stream) has worked --Jack 13:34, 24 November 2008 (NZDT)
I have got flv embeds working using the flowplayer extension and raw HTML, and now need to rewrite my extension to suit --Jack 11:17, 27 November 2008 (NZDT)

ffmpeg Issues

A cut down version of the simple binary stream return has worked, although the page that comes up is an error page with "The action specified by the URL is not recognized by the wiki", which i would like to suppress --Jack 13:37, 20 November 2008 (NZDT)
How odd my local ffmpeg will not accept an url as an input parameter, I wonder if this is a Windows problem. If not, ie if ffmpeg input file has to be on the file system, then a fileread() or some way of saving the whole file locally will have to be done first, or a streaming setup established --Jack 15:33, 20 November 2008 (NZDT)
Works fine in Ubuntu so no problem :) --Jack 20:39, 20 November 2008 (NZDT)

Flowplayer embed

Embedding is now possible using the Flowplayer (Apache License 2.0) swf to play the flv generated by the embed command. The user needs to copy the FlowPlayer.swf to the upload folder. If this is not done, the extension still functions except for the embed option. To replay the video, the play-pause button needs to be clicked and the bar dragged back to the start, which is clunky but works. Only the 1.8 version of Flowplayer seems to work, as later versions rely on Flashplayer javascript embedding, but it's a nice simple interface anyway--Jack 21:39, 27 November 2008 (NZDT)

SWF

I have done some research on this and the chances of having a swf rendered are pretty bleak at the mo. FFserver does not appear to do it neither does mencoder. While there is a PERL library, http://nixbit.com/cat/programming/libraries/flv::toswf/ , it requires the installation of no fewer that seven supporting libraries, so if we can't package them up, then its useless saying we have the functionality, when every user has to install these eight libraries. --Jack 10:10, 10 December 2008 (NZDT)

Have a look at this. I've tested it and it definitely produces a swf. --Rob 10:43, 10 December 2008 (NZDT)