
Recherche avancée
Médias (29)
-
#7 Ambience
16 octobre 2011, par
Mis à jour : Juin 2015
Langue : English
Type : Audio
-
#6 Teaser Music
16 octobre 2011, par
Mis à jour : Février 2013
Langue : English
Type : Audio
-
#5 End Title
16 octobre 2011, par
Mis à jour : Février 2013
Langue : English
Type : Audio
-
#3 The Safest Place
16 octobre 2011, par
Mis à jour : Février 2013
Langue : English
Type : Audio
-
#4 Emo Creates
15 octobre 2011, par
Mis à jour : Février 2013
Langue : English
Type : Audio
-
#2 Typewriter Dance
15 octobre 2011, par
Mis à jour : Février 2013
Langue : English
Type : Audio
Autres articles (40)
-
Amélioration de la version de base
13 septembre 2013Jolie sélection multiple
Le plugin Chosen permet d’améliorer l’ergonomie des champs de sélection multiple. Voir les deux images suivantes pour comparer.
Il suffit pour cela d’activer le plugin Chosen (Configuration générale du site > Gestion des plugins), puis de configurer le plugin (Les squelettes > Chosen) en activant l’utilisation de Chosen dans le site public et en spécifiant les éléments de formulaires à améliorer, par exemple select[multiple] pour les listes à sélection multiple (...) -
Menus personnalisés
14 novembre 2010, parMediaSPIP utilise le plugin Menus pour gérer plusieurs menus configurables pour la navigation.
Cela permet de laisser aux administrateurs de canaux la possibilité de configurer finement ces menus.
Menus créés à l’initialisation du site
Par défaut trois menus sont créés automatiquement à l’initialisation du site : Le menu principal ; Identifiant : barrenav ; Ce menu s’insère en général en haut de la page après le bloc d’entête, son identifiant le rend compatible avec les squelettes basés sur Zpip ; (...) -
Supporting all media types
13 avril 2011, parUnlike most software and media-sharing platforms, MediaSPIP aims to manage as many different media types as possible. The following are just a few examples from an ever-expanding list of supported formats : images : png, gif, jpg, bmp and more audio : MP3, Ogg, Wav and more video : AVI, MP4, OGV, mpg, mov, wmv and more text, code and other data : OpenOffice, Microsoft Office (Word, PowerPoint, Excel), web (html, CSS), LaTeX, Google Earth and (...)
Sur d’autres sites (6888)
-
Cannot find configure.ac file in ffmpeg
23 février 2014, par SudheeshWhere can I find the configure.ac file of ffmpeg ?. I downloaded the latest version of ffmpeg from git, but couldn't find the configure.ac ( input for autoconf ).
I am in the process of adding a new proprietary media encoding/decoding in ffmpeg. I plan to enable it via —enable-mylib ( like libfaac ). Hence the question.
-
Working on images asynchronously
To get my quota on buzzwords for the day we are going to look at using ZeroMQ and Imagick to create a simple asynchronous image processing system. Why asynchronous ? First of all, separating the image handling from a interactive PHP scripts allows us to scale the image processing separately from the web heads. For example we could do the image processing on separate servers, which have SSDs attached and more memory. In this example making the images available to all worker nodes is left to the reader.
Secondly, separating the image processing from a web script can provide more responsive experience to the user. This doesn’t necessarily mean faster, but let’s say in a multiple image upload scenario this method allows the user to do something else on the site while we process the images in the background. This can be beneficial especially in cases where users upload hundreds of images at a time. To achieve a simple distributed image processing infrastructure we are going to use ZeroMQ for communicating between different components and Imagick to work on the images.
The first part we are going to create is a simple “Worker” -process skeleton. Naturally for a live environment you would like to have more error handling and possibly use pcntl for process control, but for the sake of brewity the example is barebones :
-
< ?php
-
-
define (’THUMBNAIL_ADDR’, ’tcp ://127.0.0.1:5000’) ;
-
define (’COLLECTOR_ADDR’, ’tcp ://127.0.0.1:5001’) ;
-
-
class Worker {
-
-
private $in ;
-
private $out ;
-
-
public function __construct ($in_addr, $out_addr)
-
{
-
$context = new ZMQContext () ;
-
-
$this->in = new ZMQSocket ($context, ZMQ: :SOCKET_PULL) ;
-
$this->in->bind ($in_addr) ;
-
-
$this->out = new ZMQSocket ($context, ZMQ: :SOCKET_PUSH) ;
-
$this->out->connect ($out_addr) ;
-
}
-
-
public function work () {
-
while ($command = $this->in->recvMulti ()) {
-
if (isset ($this->commands [$command [0]])) {
-
echo "Received work" . PHP_EOL ;
-
-
$callback = $this->commands [$command [0]] ;
-
-
array_shift ($command) ;
-
$response = call_user_func_array ($callback, $command) ;
-
-
if (is_array ($response))
-
$this->out->sendMulti ($response) ;
-
else
-
$this->out->send ($response) ;
-
}
-
else {
-
error_log ("There is no registered worker for $command [0]") ;
-
}
-
}
-
}
-
-
public function register ($command, $callback)
-
{
-
$this->commands [$command] = $callback ;
-
}
-
}
-
?>
The Worker class allows us to register commands with callbacks associated with them. In our case the Worker class doesn’t actually care or know about the parameters being passed to the actual callback, it just blindly passes them on. We are using two separate sockets in this example, one for incoming work requests and one for passing the results onwards. This allows us to create a simple pipeline by adding more workers in the mix. For example we could first have a watermark worker, which takes the original image and composites a watermark on it, passes the file onwards to thumbnail worker, which then creates different sizes of thumbnails and passes the final results to event collector.
The next part we are going to create a is a simple worker script that does the actual thumbnailing of the images :
-
< ?php
-
include __DIR__ . ’/common.php’ ;
-
-
// Create worker class and bind the inbound address to ’THUMBNAIL_ADDR’ and connect outbound to ’COLLECTOR_ADDR’
-
$worker = new Worker (THUMBNAIL_ADDR, COLLECTOR_ADDR) ;
-
-
// Register our thumbnail callback, nothing special here
-
$worker->register (’thumbnail’, function ($filename, $width, $height) {
-
$info = pathinfo ($filename) ;
-
-
$out = sprintf ("%s/%s_%dx%d.%s",
-
$info [’dirname’],
-
$info [’filename’],
-
$width,
-
$height,
-
$info [’extension’]) ;
-
-
$status = 1 ;
-
$message = ’’ ;
-
-
try {
-
$im = new Imagick ($filename) ;
-
$im->thumbnailImage ($width, $height) ;
-
$im->writeImage ($out) ;
-
}
-
catch (Exception $e) {
-
$status = 0 ;
-
$message = $e->getMessage () ;
-
}
-
-
return array (
-
’status’ => $status,
-
’filename’ => $filename,
-
’thumbnail’ => $out,
-
’message’ => $message,
-
) ;
-
}) ;
-
-
// Run the worker, will block
-
echo "Running thumbnail worker.." . PHP_EOL ;
-
$worker->work () ;
As you can see from the code the thumbnail worker registers a callback for ‘thumbnail’ command. The callback does the thumbnailing based on input and returns the status, original filename and the thumbnail filename. We have connected our Workers “outbound” socket to event collector, which will receive the results from the thumbnail worker and do something with them. What the “something” is depends on you. For example you could push the response into a websocket to show immediate feeedback to the user or store the results into a database.
Our example event collector will just do a var_dump on every event it receives from the thumbnailer :
-
< ?php
-
include __DIR__ . ’/common.php’ ;
-
-
$socket = new ZMQSocket (new ZMQContext (), ZMQ: :SOCKET_PULL) ;
-
$socket->bind (COLLECTOR_ADDR) ;
-
-
echo "Waiting for events.." . PHP_EOL ;
-
while (($message = $socket->recvMulti ())) {
-
var_dump ($message) ;
-
}
-
?>
The final piece of the puzzle is the client that pumps messages into the pipeline. The client connects to the thumbnail worker, passes on filename and desired dimensions :
-
< ?php
-
include __DIR__ . ’/common.php’ ;
-
-
$socket = new ZMQSocket (new ZMQContext (), ZMQ: :SOCKET_PUSH) ;
-
$socket->connect (THUMBNAIL_ADDR) ;
-
-
$socket->sendMulti (
-
array (
-
’thumbnail’,
-
realpath (’./test.jpg’),
-
50,
-
50,
-
)
-
) ;
-
echo "Sent request" . PHP_EOL ;
-
?>
After this our processing pipeline will look like this :
Now, if we notice that thumbnail workers or the event collectors can’t keep up with the rate of images we are pushing through we can start scaling the pipeline by adding more processes on each layer. ZeroMQ PUSH socket will automatically round-robin between all connected nodes, which makes adding more workers and event collectors simple. After adding more workers our pipeline will look like this :
Using ZeroMQ also allows us to create more flexible architectures by adding forwarding devices in the middle, adding request-reply workers etc. So, the last thing to do is to run our pipeline and see the results :
Let’s create our test image first :
$ convert magick:rose test.jpg
From the command-line run the thumbnail script :
$ php thumbnail.php Running thumbnail worker..
In a separate terminal window run the event collector :
$ php collector.php Waiting for events..
And finally run the client to send the thumbnail request :
$ php client.php Sent request $
If everything went according to the plan you should now see the following output in the event collector window :
array(4) [0]=> string(1) "1" [1]=> string(56) "
/test.jpg" [2]=> string(62) " /test_50x50.jpg" [3]=> string(0) "" Happy hacking !
-
-
Zlib vs. XZ on 2SF
I recently released my Game Music Appreciation website. It allows users to play an enormous range of video game music directly in their browsers. To do this, the site has to host the music. And since I’m a compression bore, I have to know how small I can practically make these music files. I already published the results of my effort to see if XZ could beat RAR (RAR won, but only slightly, and I still went with XZ for the project) on the corpus of Super Nintendo chiptune sets. Next is the corpus of Nintendo DS chiptunes.
Repacking Nintendo DS 2SF
The prevailing chiptune format for storing Nintendo DS songs is the .2sf format. This is a subtype of the Portable Sound Format (PSF). The designers had the foresight to build compression directly into the format. Much of payload data in a PSF file is compressed with zlib. Since I already incorporated Embedded XZ into the player project, I decided to try repacking the PSF payload data from zlib -> xz.In an effort to not corrupt standards too much, I changed the ’PSF’ file signature (seen in the first 3 bytes of a file) to ’psf’.
Results
There are about 900 Nintendo DS games currently represented in my website’s archive. Total size of the original PSF archive, payloads packed with zlib : 2.992 GB. Total size of the same archive with payloads packed as xz : 2.059 GB.Using xz vs. zlib saved me nearly a gigabyte of storage. That extra storage doesn’t really impact my hosting plan very much (I have 1/2 TB, which is why I’m so nonchalant about hosting the massive MPlayer Samples Archive). However, smaller individual files translates to a better user experience since the files are faster to download.
Here is a pretty picture to illustrate the space savings :
The blue occasionally appears to dip below the orange but the data indicates that xz is always more efficient than zlib. Here’s the raw data (comes in vanilla CSV flavor too).
Interface Impact
So the good news for the end user is that the songs are faster to load up front. The downside is that there can be a noticeable delay when changing tracks. Even though all songs are packaged into one file for download, and the entire file is downloaded before playback begins, each song is individually compressed. Thus, changing tracks triggers another decompression operation. I’m toying the possibility of some sort of background process that decompresses song (n+1) while playing song (n) in order to help compensate for this.I don’t like the idea of decompressing everything up front because A) it would take even longer to start playing ; and B) it would take a huge amount of memory.
Corner Case
There was at least one case in which I found zlib to be better than xz. It looks like zlib’s minimum block size is smaller than xz’s. I think I discovered xz to be unable to compress a few bytes to a block any smaller than about 60-64 bytes while zlib got it down into the teens. However, in those cases, it was more efficient to just leave the data uncompressed anyway.