The nightmare of tagging multiple photos with digiKam, and a hacky way around it. Part II

Yesterday I posted about how to put multiple tags in tons of pictures, with [[digiKam]]. Apparently, the method I described there does not work (blame it on digiKam, of course). Still, the post makes for an interesting reading (hey, I am the author. What would I say?).

Here I’ll describe a new way to acomplish what the previous method couldn’t. If you want to know what on Earth I’m talking about, read the The problem section of the previous post.

Fairy tale-like solution

I found out how to implement a solution much like the one in the Fairy tale solution section of my previous post. Question: what is the next best thing to a single keystroke to tag a file? Answer: a single mouse click.

Following our ideal method, we will do a visual scan of all photos, one by one, succesively tagging (or ignoring) each file in which a certain person appears (or doesn’t). The tagging will be done by a single mouse click (right hand always on mouse), and the photos will advance with space bar strokes (left thumb always on space bar).

To do so, one must go to the first picture in the set, and maximize it. Next, open the right panel, and go to the Captions/Tags tab. Find the tag of the person you are dealing with in the tag tree, and place the mouse over it. See the following screenshot (click on it to maximize):

I assure you the fabled person A is hidding somewhere within those Cuban trees

Now, place your left hand on the keyboard (to hit the space bar), and let the fun begin. Each time person A appears in a photo, left-click with the mouse (never ever move the pointer from the tag. Space bar will make the photos advance wherever the mouse pointer is). When it doesn’t, ignore and go on. When you reach the last pic, rinse, and repeat for persons B through Z.

With this method I tagged 197 pictures in under one hour yesterday. A bit over 3 pictures tagged per minute does not look too impressive, but the 197 pictures contained 9 different persons (9 tags to apply), each one of which appeared in roughly 30 pictures. This means I did 9 slide shows of all the pictures, applying a total of more than 250 tags.

Linearly scaling method

The above method is very fast with respect to each tag applied. However it scales up quite badly, because it is slower the more pictures one has to tag (obviously), and also the more different tags one is applying (one full scan of the picture set per individual tag to apply). The dependency with pic count is unavoidable, but let’s see if we can devise a way to reduce the impact of the latter.

We begin by grouping all the potential tags (say, all people who appear in the set of pictures) within a single parent tag (see following screenshot):

A’s friend, C, is somewhere over there, as well. Do you C him?

Now, we can follow steps similar to the ones above, for the fairy tale method, but for each picture we will apply tags for all people appearing in it. This will make tagging each picture slower, but will require a single pass. Doesn’t a single N-times-slower pass take as long as N fast passes? Yes. But recall our single pass here will not take N times longer (assuming N people to tag for). A lot of pictures with no people on it will be just as fast to (not) tag as in the method above, plus most photos will feature one or two people, and very seldom will all N people appear together, so this single pass will not be N-times slower than our N passes above.

[Update]: After writing this post, I put the second method here to test, and tagged almost 1300 pics in one hour!

Comments (2)

The nightmare of tagging multiple photos with digiKam, and a hacky way around it

[Update and big fat warning]: apparently, renaming or moving files does mess with the tags the image already has. A way around this, and maybe a generally good idea (use your own judgement on that one), is to make digiKam save the tags as [[metadata]] into the picture files themselves. On the con side, tagging your pictures will actually modify the files (maybe you don’t want that), but on the pro side, the tags will travel along with the files, no matter what name or location they have (even to other computers, which may or may not be what you want).

[Update #2]: apparently the metadata approach doesn’t work either. It seems that each time a tag is assigned, the metadata is immediately saved (which is great), but only the tags digiKam is aware of at that moment. Also, digiKam is not immediately aware of the tag metadata of the pics it’s showing (you have to tell him so, I think). Let’s say you tag a pic as “A”. Metadata for “A” is saved. OK. Now, you change the name of the file, and digiKam loses track of it. You rename back, and digiKam thinks the picture has no tag (the metadata is obviously still there, inside the file, but digiKam doesn’t read it until you tell it to). Now, you assign tag “B” to the picture, expecting the file to end up with both tags: A and B. Tough luck. The split second you tag the file with “B”, it is written to the metadata (OK), but only tag B is written (the only one digiKam is aware of at that moment), so tag “A” is lost. In two words: the following post is full of crap. If a third word is allowed, let me say that digiKam is too.

First off, let me admit that my problem might have a simple solution. Maybe my goal is much simpler to achieve than I think. But what I am doing seems fairly common to me, and a pain-free recipe to do it escapes me.

The problem

I use [[digiKam]] to manage my photo collection. A very handy (and basic) function of digiKam is to tag photos. I tag photos with three criteria: where it was taken (e.g. “Donostia”), the event it can be framed within (e.g. “Wedding of A and B”), and a tag per person that appears in it (e.g. “John Smith”, “Jane Doe” and “Janet Johnson”). It involves some work, but afterwards I can really easily find say, all pictures in which John Smith and Jane Doe appear together, in any place but Donostia. Why I would want to do that is anyone’s guess, but that’s offtopic.

Every time I have a batch of photos (say, a wedding or some holidays), I sit down in front of my computer, and tag evey one of them. Tagging by event is a breeze (99.9% of the time, the whole batch of pics belongs to the same event), and tagging by location is also simple (each pic has a single location, and many, if not all, share that location). However, tagging by person is a bit trickier. Each photo can have many (or no) people appearing on it, plus it takes a bit of attention to spot all people appearing.

When tagging by people, two approaches can be taken:

  1. Parse photo by photo, tagging each one once per person appearing on it. Don’t move to the next photo until tags for eveyone appearing on current one have been asigned.
  2. Parse whole batch, once per person. You pick a person, select all pics where she appears, then you tag all of them simultaneously. Repeat for each person.

I have found that, for large amounts of pictures, the second approach is fairly superior. However, it is not problem-free. Firstly, multiple selection is only possible in a grid view. That is, pictures are presented as [[thumbnails]], aligned in columns and rows. Even in the largest possible size for such pictures, often times there are many photos that are too small to spot all people in them. Secondly, having selected some dozens of pictures out of some hundreds, and mistakenly unselecting them by clicking where you shouldn’t, or failing to hold the Ctrl key when clicking (or whatever error whose probability to happen increases with the amount of pictures to tag) is just painful.

Fairy tale solution

I realized a hybrid method would be advantageous, but that’s where the problem comes: I find no simple way to accomplish it. I would like to be able to do the following comfortably: inspect the photos one by one, tagging each one in which person A appears. When all are tagged, repeat for person B, and so on. Right now this approach will take longer than either approaches above, because it borrows the worse characteristics from both (one-by-one tagging of method 1, scanning all the photos repeatedly, once per person, from method 2). The reason for that is that asigning a single tag to a single photo is cumbersome. You right-click on the photo, then select “Assign Tag” from the menu that appears, then choose a tag from the drop-down menu (and submenus if case be).

There is no shortcut that one can assign to some tag, or, even better, a single-key shortcut for “assign to this photo the last tag I have assigned to the previous one”. If there was, my hybrid approach would be really fast: take person A, appearing in picture 1. Tag pic 1 with “A”. Then go picture by picture (a single hit of the space bar), either ignoring the pics where person “A” does not appear, or pressing the “apply last tag” shortcut (a single keystroke) where she does.

Hacky solution

Of the tools that digiKam offers, which one can modify a photo in a way that the contents are not touched, yet we can group them afterwards based on that change? Easy: rename (F2 key). When you press F2, a rename dialog appears, with a field where you can enter the new name for the currently selected pic. The good thing is the field is already filled with the current name of the photo. So, if you want to rename a photo to, say, the same name but with a trailing dot, all you have to do is press the sequence: F2 + . + Enter.

Now, how on Earth would the renaming help? Well, we could use the above “trick” to quickly rename all pictures in which person A appears, making all of them have the same name, but with a trailing dot added. Then, we could Alt-Tab to a terminal, cd to the dir where the photos reside, and execute the following ([[Z shell|zsh]] syntax, translate to your favorite shell):

% mkdir totag
% for file in *.; mv $file totag/`echo $file | sed ‘s/.$//’`

That will put all files ending in a dot inside a subfolder called “totag”, renaming them back to their original name (chopping off the last character, which would be the dot). Don’t forget the fact that these files happen to be all in which person A appears. Recall as well that digiKam keeps track of the tags applied to each photo by its [[md5sum]] (OK, I made that up, but it must be true), so moving files around and/or renaming them (both things are one and the same, actually) doesn’t mess with the tags. (see warning at the top of this post).

So, once all pics with person A reside in folder “totag”, we can Alt-Tab back to digiKam, go to that folder, select all pics, and tag them all at once. After that, Alt-Tab to the terminal, and execute:

% mv totag/* .

The real beauty of using a shell for that (even with the apparently complicated command with the for loop above), is that you can reuse the commands trivially. For person B, once all relevant photos have been renamed with a dot, Alt-Tab to the terminal, hit the Up arrow twice, then Enter, and you will move and rename all files again in just three keystrokes (two of them being the same key hit twice). Alt-Tab to digiKam, tag all pics in the “totag” dir. Alt-Tab to the terminal, Up+Up+Enter (which now executes the mv), and you have the files in the main dir again.

Conclusion

Yeah, I bet right now you are considering whether my idea of what is “simple” or “comfortable” is seriously off. I’d still vote for the “Reapply last tag” shortcut in digiKam. It would make a three-keystroke step (F2+.+Enter, to rename) a single keystroke one (reapply last tag with shortcut), plus would make the steps involving the terminal unnecessary. But reality is a bitch, and we don’t have such a shortcut. I could either just rant about it on my blog, or go ahead and find a solution myself. I chose to do both :^)

Comments (4)

Scrobbling to Last.fm with Amarok 2.3 and no Kwallet

I am not a great [[KWallet]] fan (probably due to ignorance), so when I introduce my [[Last.fm]] credentials in [[Amarok (software)|Amarok]] I get this warning that they will be saved in plain text (because Kwallet is not running). That didn’t bother me much, until recently. As it happens, my computer at work (Amarok 2.3 on [[Arch Linux]]) does not scrobble (publish) the tracks I play into Last.fm.

The root of the problem seems to be that my Last.fm credentials are not actually saved. If I go to Settings -> Configure Amarok -> Internet Services -> Last.fm, I can write my “Username” and “Password” there. If I click on “Test login”, it will report a success for valid credentials, and a failure for wrong ones. If I click “OK” (that is, save and exit), the aforementioned warning about Kwallet not running appears (no big deal so far), and if I choose to accept the proposal of saving the password in plain text Amarok seems to accept it. The problem is, it doesn’t really. My tracks don’t get scrobbled, and if I go to the Last.fm settings again, the credentials are empty.

In my computer at home, with an identical Amarok 2.3 on Arch Linux and with no Kwallet, the credentials do get saved, and the scrobbling does work. It might well be because I alreadly applied the trick I will explain next (and I don’t remember having done it). I came accross the solution at bug report 555688 at [[ Launchpad_(website)|Launchpad]], the Ubuntu bugtracking site.

The solution is simple. Edit the following file:

~/.kde4/share/config/amarokrc

and add the following (section [Service_LastFm] will most likely already exist):

[Service_LastFm]
fetchSimilar=true
ignoreWallet=yes
password=YOURPASSWORD
scrobble=true
username=YOURUSERNAME

where YOURPASSWORD and YOURUSERNAME must obviously be changed for the appropriate values.

Comments (8)

Please, choose the right format to send me that text. Thanks.

I just received an e-mail with a very interesting text (recipies for [[Pincho|pintxos]]), and it prompted some experiment. The issue is that the text was inside of a [[DOC (computing)|DOC]] file (of course!), which rises some questions and concerns on my side. The size of the file was 471 kB.

I thought that one could make the document more portable by exporting it to [[PDF]] (using [[OpenOffice.org]]). Doing so, the resulting file has a size of 364 kB (1.29 times smaller than the original DOC).

Furthermore, text formatting could be waived, by using a [[plain text]] format. A copy/paste of the contents of the DOC into a TXT file yielded a 186 kB file (2.53x smaller).

Once in the mood, we can go one step further, and compress the TXT file: with [[gzip]] we get a 51 kb file (9.24x), and with [[xz]] a 42 kB one (11.2x)

So far, so good. No surprise. The surprise came when, just for fun, I exported the DOC to [[OpenDocument|ODT]]. I obtained a document equivalent to the original one, but with a 75 kB size! (6.28x smaller than the DOC).

So, for summarizing:

DOC

Pros

  • Editable.
  • Allows for text formatting.

Cons

  • Proprietary. In principle only MS Office can open it. OpenOffice.org can, but because of reverse engineering.
  • If opened with OpenOffice.org, or just a different version of MS Office, the reader can not be sure of seeing the same formatting the writer intended.
  • Size. 6 times bigger than ODT. Even bigger than PDF.
  • MS invented and owns it. You need more reasons?

PDF

Pros

  • Portability. You can open it in any OS (Windows, Linux, Mac, BSD…), on account of there being so many free PDF readers.
  • Smaller than the DOC.
  • Allows for text formatting, and the format the reader sees will be exactly the one the writer intended.

Cons

  • Not editable (I really don’t see the point in editing PDFs. For me the PDF is a product of an underlying format (e.g. LaTeX), as what you see on your browser is the product of some HTML/PHP, or an exe is the product of some source code. But I digress.)
  • Could be smaller

TXT

Pros

  • Portability. You can’t get much more portable than a plain text file. You can edit it anywhere, with your favorite text editor.
  • Size. You can’t get much smaller than a plain text file (as it contains the mere text content), and you can compress it further with ease.

Cons

  • Formatting. If you need text formatting, or including pictures or content other than text, then plain text is not for you.

ODT

Pros

  • Portability. It can be edited with OpenOffice.org (and probably others), which is [[free software]], and has versions for Windows, Linux, and Mac.
  • Editability. Every bit as editable as DOC.
  • Size. 6 times smaller files than DOC.
  • It’s a free standard, not some proprietary rubbish.

Cons

  • None I can think of.

So please, if you send me some text, first consider if plain text will suffice. If not, and no edition is intended on my side, PDF is fine. If edition is important (or size, because it’s smaller than PDF), the ODT is the way to go.

Comments (7)

Speed up PyGTK and Cairo by reusing images

As you might have read in this blog, I own a Neo FreeRunner since one year ago. I have used it far less than I should have, mostly because it’s a wonderful toy, but a lousy phone. The hardware is fine, although externally quite a bit less sexy than other smartphones such as the iPhone. The software, however, is not very mature. Being as open as it is, different Linux-centric distros have been developed for it, but I haven’t been able to find one that converts the Neo into an everyday use phone.

But let’s cut the rant, and stick to the issue: that the Neo is a nice playground for a computer geek. Following my desire to play, I installed Debian on it. Next, I decided to make some GUI programs for it, such a screen locker. I found Zedlock, a program written in Python, using GTK+ and Cairo. Basically, Zedlock paints a lock on the screen, and refuses to disappear until you paint a big “Z” on the screen with your finger. Well, that’s what it’s supposed to do, because the 0.1 version available at the Openmoko wiki is not functional. However, with Zedlock I found just what I wanted: a piece of software capable of doing really cool graphical things on the screen of my Neo, while being simple enough for me to understand.

Using Zedlock as a base, I am starting to have real fun programming GUIs, but a problem has quickly arisen: their response is slow. My programs, as all GUIs, draw an image on the screen, and react to tapping in certain places (that is, buttons) by doing things that require that the image on the screen be modified and repainted. This repainting, done as in Zedlock, is too slow. To speed things up, I googled the issue, and found a StackOverflow question that suggested the obvious route: to cache the images. Let’s see how I did it, and how it turned out.

Material

You can download the three Python scripts, plus two sample PNGs, from: http://isilanes.org/pub/blog/pygtk/.

Version 0

You can download this program here. Its main loop follows:

C = Canvas()

# Main window:
C.win = gtk.Window()
C.win.set_default_size(C.width, C.height)

# Drawing area:
C.canvas = gtk.DrawingArea()
C.win.add(C.canvas)
C.canvas.connect('expose_event', C.expose_win)

C.regenerate_base()

# Repeat drawing of bg:
try:
  C.times = int(sys.argv[1])
except:
  C.times = 1

gobject.idle_add(C.regenerate_base)
C.win.show_all()

# Main loop:
gtk.main()

As you can see, it generates a GTK+ window (line 04), with a DrawingArea inside (line 08), and then executes the regenerate_base() function every time the main loop is idle (line 20). Canvas() is a class whose structure is not relevant for the discussion here. It basically holds all variables and relevant functions. The regenerate_base() function follows:

def regenerate_base(self):
    
    # Base Cairo Destination surface:
    self.DestSurf = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.width, self.height)
    self.target   = cairo.Context(self.DestSurf)
  
    # Background:
    if self.bg == 'bg1.png':
      self.bg = 'bg2.png'
    else:
      self.bg = 'bg1.png'

    self.i += 1

    image       = cairo.ImageSurface.create_from_png(self.bg)
    buffer_surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.width, self.height)
    buffer      = cairo.Context(buffer_surf)
    buffer.set_source_surface(image, 0,0)
    buffer.paint()
  
    self.target.set_source_surface(buffer_surf, 0, 0)
    self.target.paint()
  
    # Redraw interface:
    self.win.queue_draw()

    if self.i > self.times:
      sys.exit()

    return True

As you can see, it paints the whole window with a PNG file (lines 15-25), choosing alternately bg1.png and bg2.png each time it is called (lines 07-11). Since the re-painting is done every time the main event loop is idle, it just means that images are painted to screen as fast as possible. After a given amount of re-paintings, the script exits.

You can run the code above by placing two suitable PNGs (480×640 pixels) in the same directory as the above code. If an integer argument is given to the script, it re-paints the window that many times, then exits (default, just once). You can time this script by executing, e.g.:

% /usr/bin/time -f %e ./p0.py 1000

Version 1

You can download this version here.

The first difference with p1.py is that the regenerate_base() function has been separated into the first part (generate_base()), which is executed only once at program startup (see below), and all the rest, which is executed every time the background is changed.

def generate_base(self):

    # Base Cairo Destination surface:
    self.DestSurf = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.width, self.height)
    self.target   = cairo.Context(self.DestSurf)

The main difference, though, is that two new functions are introduced:

  def mk_iface(self):

    if not self.bg in self.buffers:
      self.buffers[self.bg] = self.generate_buffer(self.bg)

    self.target.set_source_surface(self.buffers[self.bg], 0, 0)
    self.target.paint()

  def generate_buffer(self, fn):

    image       = cairo.ImageSurface.create_from_png(fn)
    buffer_surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.width, self.height)
    buffer      = cairo.Context(buffer_surf)
    buffer.set_source_surface(image, 0,0)
    buffer.paint()
  
    # Return buffer surface:
    return buffer_surf

The function mk_iface() is called within regenerate_base(), and draws the background. However, the actual generation of the background image (the Cairo surface) is done in the second function, generate_buffer(), and only happens once per each background (i.e., twice in total), because mk_iface() reuses previously generated (and cached) surfaces.

Version 2

You can download this version here.

The difference with Revision 1 is that I eliminated some apparently redundant procedures for creating surfaces upon surfaces. As a result, the generate_base() function disappears again. I get rid of the DestSurf and C.target variables, so the mk_iface() and expose_win() functions end up as follows:

  def mk_iface(self):

    if not self.bg in self.buffers:
      self.buffers[self.bg] = self.generate_buffer(self.bg)

    buffer = self.canvas.window.cairo_create()
    buffer.set_source_surface(self.buffers[self.bg],0,0)
    buffer.paint()

  def expose_win(self, drawing_area, event):

    nm = 'bg1.png'

    if not nm in self.buffers:
      self.buffers[nm] = self.generate_buffer(nm)

    ctx = drawing_area.window.cairo_create()
    ctx.set_source_surface(self.buffers[nm], 0, 0)
    ctx.paint()

A side effect is that I can get also rid of the forced redraws of self.win.queue_draw().

Results

I have run the three versions above, varying the C.times variable, i.e., making a varying number of reprints. The command used (actually inside a script) would be something like the one mentioned above:

% /usr/bin/time -f %e ./p0.py 1000

The following table sumarizes the results for Flanders and Maude (see my computers), a desktop P4 and my Neo FreeRunner, respectively. All times in seconds.

Flanders
Repaints Version 0 Version 1 Version 2
1 0.26 0.43 0.33
4 0.48 0.40 0.42
16 0.99 0.43 0.40
64 2.77 0.76 0.56
256 9.09 1.75 1.15
1024 37.03 6.26 3.44
Maude
Repaints Version 0 Version 1 Version 2
1 4.17 4.70 5.22
4 8.16 6.35 6.41
16 21.58 14.17 12.28
64 75.14 44.43 35.76
256 288.11 165.58 129.56
512 561.78 336.58 254.73

Data in the tables above has been fitted to a linear equation, of the form t = A + B n, where n is the number of repaints. In that equation, parameter A would represent a startup time, whereas B represents the time taken by each repaint. The linear fits are quite good, and the values for the parameters are given in the following tables (units are milliseconds, and milliseconds/repaint):

Flanders
Parameter Version 0 Version 1 Version 2
A 291 366 366
B 36 6 3
Maude
Parameter Version 0 Version 1 Version 2
A 453 3218 4530
B 1092 648 487

Darn it! I have mixed feelings for the results. In the desktop computer (Flanders), the gains are huge, but hardly noticeable. Cacheing the images (Version 1) makes for a 6x speedup, whereas Version 2 gives another twofold increase in speed (a total of 12x speedup!). However, from a user’s point of view, a 36 ms refresh is just as immediate as a 6 ms refresh.

On the other hand, on the Neo, the gains are less spectacular: the total gain in speed for Version 2 is a mere 2x. Anyway, half-a-second repaints instead of one-second ones are noticeable, so there’s that.

And at least I had fun and learned in the process! :^)

Comments (2)

LWD – March 2010

This is a continuation post for my Linux World Domination project, started in this May 2008 post. You can read the previous post in the series here.

In the following data T2D means “time to domination” (the expected time for Windows/Linux shares to cross, counting from the present date). DT2D means difference (increase/decrease) in T2D, with respect to last report. CLP means “current Linux Percent”, as given by last logged data, and DD means domination day (in YYYY-MM-DD format), and DCLP means “difference in CLP”, with respect to last logged data.

Project T2D DT2D DD CLP DCLP
Einstein already crossed September 2009 54.80 +3.45
MalariaControl >10 years 12.12 +0.17
PrimeGrid >10 years 11.78 +1.47
POEM >10 years 11.52 +0.69
Rosetta >10 years 8.61 +0.01
SETI >10 years 8.12 +0.05
QMC >10 years 8.11 -0.12
Spinhenge >10 years 4.46 +0.09

The numbers (again) seem a bit discouraging, but the data is what it is. Now MalariaControl goes up (it went down in previous report), but QMC goes slightly down. All others go up. The Linux tide seems unstoppable, however its forward speed is not necessarily high.

As promised, today I’m showing the plots for Spinhenge@home. In next issue, QMC@home.

Number of hosts percent evolution for Spinhenge@home (click to enlarge)

Accumulated credit percent evolution for Spinhenge@home (click to enlarge)

Comments

Avoiding time_increment_bits problem when encoding bad header MPEG4 videos to Ogg Theora

There is some debate going on lately about the migration of YouTube to [[HTML5]], and whether they (i.e. YouTube’s owner, Google) should support [[H.264]] or [[Theora]] as standard codecs for the upcoming <video> tag. See, for example, how the FSF asks for support for Theora.

The thing is, I discovered [[x264]] not so long ago, and I thought it was a “free version” of H.264. I began using it to reencode the medium-to-low quality videos I keep (e.g., movies and series). The resulting quality/file size ratio stunned me. I could reencode most material downloaded from e.g. p2p sources to 2/3 of their size, keeping the copy indistinguishable from the original with the bare eye.

However, after realizing that x264 is just a free implementation of the proprietary H.264 codec, and in the wake of the H.264/Theora debate, I decided to give Ogg Theora a go. I expected a fair competitor to H.264, although still noticeably behind in quality/size ratio. And that I found. I for one do not care if I need a 10% larger file to attain the same quality, if it means using free formats, so I decided to adopt Theora for everyday reencoding.

After three paragraphs of introduction, let’s get to the point. Which is that reencoding some files with [[ffmpeg2theora]] I would get the following error:

% ffmpeg2theora -i example_video.avi -o output.ogg
[avi @ 0x22b7560]Something went wrong during header parsing, I will ignore it and try to continue anyway.
[NULL @ 0x22b87f0]hmm, seems the headers are not complete, trying to guess time_increment_bits
[NULL @ 0x22b87f0]my guess is 15 bits ;)
[NULL @ 0x22b87f0]looks like this file was encoded with (divx4/(old)xvid/opendivx) -> forcing low_delay flag
Input #0, avi, from 'example_video.avi':
  Metadata:
    Title           : example_video.avi
  Duration: 00:44:46.18, start: 0.000000, bitrate: 1093 kb/s
    Stream #0.0: Video: mpeg4, yuv420p, 624x464, 23.98 tbr, 23.98 tbn, 23.98 tbc
    Stream #0.1: Audio: mp3, 48000 Hz, 2 channels, s16, 32 kb/s
  .

[mpeg4 @ 0x22b87f0]hmm, seems the headers are not complete, trying to guess time_increment_bits
[mpeg4 @ 0x22b87f0]my guess is 16 bits ;)
[mpeg4 @ 0x22b87f0]hmm, seems the headers are not complete, trying to guess time_increment_bits
[mpeg4 @ 0x22b87f0]my guess is 16 bits ;)
[mpeg4 @ 0x22b87f0]looks like this file was encoded with (divx4/(old)xvid/opendivx) -> forcing low_delay flag
    Last message repeated 1 times
[mpeg4 @ 0x22b87f0]warning: first frame is no keyframe

I searched the web for solutions, but to no avail. Usually pasting literal errors in Google yields good results, but in this case I only found developer forums where this bug was discussed. What I haven’t found is simple instructions on how to avoid it in practice.

Well, here it goes my simple solution: pass it through [[MEncoder]] first. Where the following fails:

% ffmpeg2theora -i input.avi -o output.ogg

the following succeeds:

% mencoder input.avi -ovc copy -oac copy -o filtered.avi
% ffmpeg2theora -i filtered.avi -o output.ogg

I guess that what happens is basically that mencoder takes the “raw” video data in input.avi and makes a copy into filtered.avi (which ends up being exactly the same video), building sane headers in the process.

Comments (3)

Amarok WTF

Warning: the following rant could be caused by my idiocy, more than by Amarok’s fault. See comments.

I have been using [[Amarok (software)|Amarok]] as music player even since I had first contact with it. I was really delighted with its capabilities, and everything was intuitive and useful in its [[User Interface|UI]]. That was until version 1.4.x.

Version 2.0 was an almost complete rewrite of the code, and as such many things changed. The UI suffered a large redesign, in my opinion for worse… but that’s just an opinion. There are, however, other issues that are facts, not opinion. Amarok 2.0 lacked many of the features of Amarok 1.x, as the developers themselves admitted (not much room to deny). Fine, I have no problem with that. It is understandable: until version 2.x things will not settle down. The only problem is that Linux distros (at least Ubuntu) adopted Amarok 2.0 almost immediately, leaving us users with a broken toy. Not nice.

My latest gripe with Amarok? I run Ubuntu 9.10 at work (Amarok 2.2.0), and latest Arch at home. In the latter, I just updated Amarok 2.2.1 to 2.2.2 in the weekend (Arch is much more up to date than Ubuntu, since it’s based in almost bleeding-edge rolling releases). Well, unlike Amarok 2.2.1 before (or Amarok 2.2.0 at work), the new Amarok 2.2.2 does not have an option for random play. Yes, you read correctly. There is no way I know of to avoid playing all the songs in the playlist in the exact order (in principle, alphabetical) they are laid on. In older versions, you could play songs or albums randomly. With 2.2.2, they lost this capability. Amazing feature regression, if you ask me.

Comments (3)

Los piratas también comen

Ya me perdonaréis que escriba dos posts seguidos sobre el mismo tema. Además en castellano, cuando procuro que el lenguaje del blog sea el inglés, simplemente por mayor alcance entre los lectores potenciales. La verdad es que muchos “artículos de opinión” me salen más naturalmente en el idioma de Cervantes, y además en este caso voy a responder a una columna publicada en una revista en castellano.

El caso es que ojeando el suplemento Mujer Hoy del periódico, concretamente el ejemplar de la primera semana de 2010, me encontré con un artículo de Julia Navarro titulado “Los escritores también comen“. En él, la señora Navarro hace una apología de la remuneración “justa” de los autores (concretamente escritores), y critica (por supuesto) la distribución de contenidos por medio de redes [[es:peer-to-peer|p2p]]. Como en el artículo se hacen una serie de argumentaciones falaces, y como los comentarios en la propia página hoymujer.com me parecen un lugar exiguo para comentarlas todas, he decidido hacerlo aquí. Si lo considero apropiado, le haré llegar un link a este post mediante un comentario en hoymujer.com (no es que piense que lo vaya a leer, pero bueno).

La señora Navarro comienza exponiendo su postura:

Perdonen que vuelva sobre el asunto, pero el debate está en la sociedad porque a muchos no les entra en la cabeza que “piratear” el trabajo ajeno debe ser delito y se han puesto de uñas ante la nueva legislación que cortará el acceso a internet a quienes se descarguen contenidos sin previo pago. Y no se me ocurre mejor manera que explicarles cómo se escribe una novela o cómo las escribo yo.

Tras esto, explica en dos párrafos el proceso creativo de un libro, y argumenta que tras cada obra hay un ser humano que ha trabajado para parirla y merece una remuneración.

Empecemos por la propia introducción: la Sra. Navarro confunde las modificaciones legislativas que el PSOE quiere hacer (¿o a hecho ya?) sobre el cierre de páginas web “piratas” por parte de una comisión gubernamental, y no jueces independientes, con la [[es:Ley Hadopi|Ley Hadopi]] de Sarkozy, que versa sobre el corte de la conexión a internet a usuarios “piratas”. No la culpo, porque en este circo mediático yo también confundo a veces de qué se está hablando. En todo caso, las críticas a la nueva legislación a la que quiere aludir la señora Navarro no tienen que ver con la “justicia” de cerrar o no páginas web, ni con si queremos “piratear” sin cortapisas, y evitar “previos pagos”. A ver si se entera ud., Sra. Navarro, que la ley lo que pretende es obviar las garantías de defensa justa de los acusados. Ya existe una legislación que contempla el cierre de cualquier sitio web que vulnere la ley, mediante decisión judicial (de manera cautelar si hiciera falta, es decir, antes de un juicio), y acompañada de juicio. Pero todos los juicios que en España se han celebrado en este sentido, han sido ganados por la defensa. Es decir, que el juez siempre ha negado la razón a la SGAE y a sus colegas (de ud.) autores acusadores. Lo que pretende la nueva ley es que, dado que un juicio justo no da la razón a quien interesa a la SGAE, digo al gobierno, sea una “comisión” (dependiente de la SGAE, digo, del gobierno) la que decida los cierres, cortocircuitando la via judicial (ya sabe ud., la separación de poderes que dice la Constitución, que es un libro también).

Sigamos por el desarrollo. Argumenta la Sra. Navarro que, dado que escribir (“crear”, como dicen los pretenciosos artistas), cuesta un esfuerzo, los artistas merecen una retribución:

Imagino que lo mismo les sucede a quienes escriben una canción, un guión o una serie de televisión. O a quienes ponen voz a esa canción o interpretan un libreto. Ese esfuerzo para crear no es mayor ni menor que ejercer la abogacía o limpiar la vía pública. Cada trabajo tiene detrás a un ser humano que merece recibir una retribución.

Esto, Sra. Navarro, es simple y llanamente falso, y dejar una pluma en manos de alguien que no lo sepa podría ser considerado imprudencia temeraria. Como ud. bien sabe, en un mercado libre capitalista (que es el que me dicen que nos rige en España, y creo que a ud. también), el precio de los bienes no está marcado por lo que cueste el producirlos, sino por lo que el comprador está dispuesto a pagar. Por poner un ejemplo absurdo, a un insomne puede costarle tanto dormir como a ud. escribir un libro, pero ello no significa que el insomne “merezca” una retribución por sus esfuerzos. Es más, y hablando de ejemplos, yo voy a seguir el suyo y le voy a hablar de mi vida como “pirata”, que diría ud.

Todo empieza con una crítica, una noticia, un anuncio… Digamos que un amigo me dice que cierta serie de TV es muy buena. La busco en una red p2p, y la encuentro. Mi conexión es muy lenta, así que tengo que ser selectivo con lo que bajo, porque tarda mucho. La pongo a bajar, y tras semanas, la tengo entera. Bien, esto es el primer paso, pero no siempre el último. Hete aquí que me la he bajado en inglés, porque prefiero las versiones originales, y porque hay más gente angloparlante compartiendo ficheros. Mi dominio del inglés es bastante aceptable, pero unos subtítulos vendrían bien. Me pongo a buscar subtítulos (para cada uno de los 25 capítulos de cada una de las 5 o 10 temporadas de la serie), y a seleccionar entre los que encuentro (no todos están igual de bien). Ahora tengo un problema: la sincronización no es perfecta. Los subtítulos salen 2 segundos antes que los actores hablen. Bueno, me hago un programilla que toma un fichero de subtítulos y lo adelanta o atrasa un tiempo arbitrario. Por amor al arte. Cuando lo termino, veo que atrasar 2 segundos los subtítulos no es suficiente, porque además lo que en el subtítulo son 10 segundos, en el vídeo son 10.5 segundos (la velocidad de reproducción no es idéntica). Bueno, modifico mi programa para permitir también “estirar” o “encoger” el subtítulo, y lo uso para adecuar el subtítulo al vídeo. Tras innumerables pruebas, veo que atrasando 2.3 segundos y estirando por un factor 1.0525 los subtítulos, estos encajan. Ya terminé el capítulo 1 de la temporada 1. Cuando pruebo el capítulo 2 veo que esos mismos factores de atraso y estiramiento no me valen. Resulta que para el segundo tengo que adelantarlos 1.1 segundos, y estirarlos un factor 1.063. Y suma y sigue.

Tras sudar un poquito subtitulando 250 capítulos (con un programa que yo mismo programé), pienso que, ya puestos, puedo recodificar el poco optimizado vídeo en [[es:DivX|DivX]] a [[es:x264|x264]], que permite mantener la calidad de imágen con un tamaño menor de fichero. Además, decido cambiar el contenedor de [[es:AVI|AVI]] a MKV ([[es:Matroska|Matroska]]), porque este último permite añadir varias pistas de audio, o varios subtítulos diferentes, todo en un mismo fichero. ¡Incluso el mismo video ocupa hasta un 5% menos en MKV que en AVI, sin variar el codec! Pero recodificar un video no es cosa de 5 minutos. Intel me agradece que me gastara dinerito en un procesador capaz, entre otras cosas, de recodificar video a una velocidad aceptable. La compañía eléctrica me agradece el gasto que mi ordenador hace cuando recodifico esos vídeos durante decenas de horas. Y nadie me agradece el tiempo que he gastado aprendiendo sobre codecs y vídeos y leches, para llegar a la conclusión de que vídeos x264 en contenedores MKV son buena opción.

Tras subtitular y recodificar los vídeos, veo que los nombres de los mismos son desafortunados. Contienen espacios, comas y signos de interrogación o exclamación, cosa desaconsejable en un nombre de fichero. Además no incluyen los nombres de los capítulos, sólo los números. Bueno, pues me hago un viaje a la Wikipedia, y busco los títulos de esos capítulos, y gasto un tiempo renombrando todos los ficheros.

Ahora que tengo los capítulos de esa serie que me gusta en un formato compacto, de buena calidad de imagen pero poco tamaño, con los subtítulos sincronizados y con nombres más cómodos y sensatos, ¿qué hago? Pues decido ser buen vecino, y compartir el resultado de mi trabajo. Lo cuelgo en la red p2p donde lo obtuve en primer lugar, anunciando que es una versión “mejor” (perdón por la soberbia) de la otra (la que yo bajé). Claro que, dado que mi conexión es asimétrica (como todas en España) tardo en subirla más de el doble de lo que tardé en bajarla. Dado que mi conexión es lenta, eso supone semanas o meses. Pero lo hago, por amor al arte.

Y tras este esfuerzo, que lo es, y tras hacerlo todo por amor al arte, porque la serie me gusta y quiero compartirla, y porque mis buenos sentimientos hacia otros usuarios de p2p me llevan a devolver el bien que ellos me hacen cuando ellos comparten lo que tienen conmigo… tras todo eso, ¿recibo una recompensa? ¿Recibo una “justa retribución”? Pues no, lo único que recibo de gente como ud. es insultos, llamándome “ladrón”. Incluso mi gobierno, en vez de loar mi actitud de defensa de la calidad de la cultura (me he esforzado por mejorar la experiencia de quien disfruta de esa serie) de manera desinteresada, me criminaliza. Me amenazan con cortarme la conexión, como en Francia. Me dicen que quiero todo “gratis total”. Por favor, reflexione dos veces antes de volver a insultarme.

Como broche final, pasemos a la postdata:

Sólo les pido a los piratas que piensen por un momento en qué sucedería si los demás consideráramos que su “trabajo”, el que hagan, debe de ser gratis total. Seguro que no les gustaría. ¿A qué no? Pues a quienes escriben, cantan, interpretan y crean tampoco nos gusta.

Esta argumentación es trístemente ubícua; la usan mucho. El problema es que es tan torticera que merece no una, sino 3 respuestas:

1) Si por “piratas” se refiere a usuarios de p2p como yo, la redirijo a los párrafos de más arriba y le contesto que mi “trabajo” ya es “gratis total”, ¿no lo ve? Mi trabajo como “pirata” consiste en distribuir contenidos y mejorarlos con un esfuerzo que nadie agradece, excepto de la manera que yo más aprecio: haciendo ellos también ese trabajo con otra serie, película o canción, y haciendo que yo lo pueda bajar. Quid pro quo, que diría el Dr. Lecter. Y sí, no solo me gusta, ¡me encanta! Es maravilloso no cobrar por un trabajo, si ello implica que los demás tampoco cobran por el suyo. Crea un ambiente de buen rollo que debería ud. probar alguna vez.

2) Obtener contenidos de redes p2p no es “gratis total”. Pagamos unos precios abusivos por las conexiones a internet, que son la vergüenza de Europa en cuanto a velocidad y precio. Pagamos por los equipos informáticos, por los routers y modems de conexión, y por los medios de almacenamiento de lo que bajamos. Todo eso cuesta dinero. Pero es más, ¡incluso nos hacen uds. pagar un canon! Pagamos por un porcentaje extra por impresoras, CDs, DVDs, discos duros, tarjetas de memoria para cámaras… ¡todo! Y lo pagamos todos, “pirateemos” o no. En mi grupo de investigación de la Universidad del País Vasco yo hacía las pequeñas compras, como CDs o DVDs, y aunque este material nunca vió una canción de Bisbal ni un libro de ud., aunque en ellos solo guardabamos información relativa a nuestra labor investigadora, ello no impedía pagar hasta un tercio del precio final en concepto de “canon”.

3) Ud. no quiere cobrar por su trabajo. A ud. le lleva meses escribir un libro, pero no quiere cobrar un salario durante esos meses. Quiere cobrarlo de por vida. Y no en concepto de “esfuerzo para escribir” sino en concepto de “derecho para usar”. Le voy a poner yo a ud. una situación inversa a la que ud. propone: le pido que piense por un momento que el médico que le salvó a ud. la vida con 15 años al extirparle el apéndice le pide durante el resto de su vida (de ud.) un pago diario por poder seguir respirando. Al fin y al cabo, sin su actuación, ud. estaría muerta. Y al taxista que la llevó a su última entrevista de trabajo, ¿le pagó solo la carrera? ¿O le paga una fracción de su salario todos los meses, porque le debe a él el haber sido contratada? ¿Paga al fontanero que arregló su fregadera por cada día que su cocina no se innunda? ¿O le pagó solo por mano de obra y piezas?

3bis) Si ud. quiere negarse a escribir un libro hasta que alguien le pague 1000 o 2000 euros al mes mientras lo escribe, está en su derecho. Nadie la puede obligar a trabajar “gratis”. Lo que ud. no puede hacer es impedir que terceros hagan copias y compartan dicha obra una vez publicada, simplemente porque eso no le reporta a ud. beneficios. Comprenda que el p2p no compite con el creador, sino con el distribuidor. El e-mail ha hecho que Correos tenga mucho menos trabajo. Es más eficiente usar un medio electrónico para hacer llegar un mensaje, que escribirlo en un medio físico y pagar a alguien para que lo transporte. La Wikipedia ha hecho que las ventas de enciclopedias tradicionales bajen. Es mucho más eficiente buscar algo en un medio electrónico que en uno físico. La Wikipedia no cuesta un dineral, no ocupa un espacio vital, y está mucho más actualizada. Al igual que las cartas físicas con el e-mail, es razonable pensar que las copias físicas de obras culturales (CDs, libros) podrían desaparecer (o palidecer) ante la distribución electrónica (p2p). ¿Apoyaría ud. que el gobierno legisle en contra de usar el e-mail, con la excusa de que Correos pierde dinero? ¿O detrás de Correos no hay seres humanos que merecen retribución? Reflexiónelo, por favor.

Comments (4)

El p2p no es robar, es compartir

Mucho se habla sobre la legitimidad de compartir material audiovisual en redes [[es:peer-to-peer|p2p]], sobre todo en el caso de materiales cubiertos por [[es:copyright|copyright]]. Las discusiones se centran principalmente en dos cuestiones: la legalidad de dicha práctica, y el efecto económico sobre un mercado (venta de copias físicas) que muchos vemos como obsoleto. Básicamente las preguntas son: ¿El Estado lo permite ahora y/o debe permitirlo en el futuro? y ¿Quién pierde y cuánto, quién gana, y cuanto?

Me gustaría añadir un ángulo diferente (aunque indudablemente tratado también por otros extensamente), y es la moralidad. Muchos pensarán que este debate está superado, porque aunque legalmente se permita el p2p, nadie en su sano juicio puede pensar que obtener algo “gratis total”, privando de ingresos al creador, es “moralmente bueno”. Nada más lejos de la realidad. Si releemos esa frase, y el párrafo anterior, vemos que ese juicio supuestamente moral está realmente basado en legalidad y/o economía, temas que deben tratarse separadamente, aunque todo esté más o menos unido. Yo me refiero a un análisis más ideológico.

Primero podríamos empezar por acotar qué es “robar”. Si nos preguntan qué es robar, la primera respuesta sería: quitar algo a alguien. Esta definición es muy buena, porque resume muy bien el problema. Quitar implica que se hace sin consentimiento, y, sobre todo, que el legítimo dueño lo pierde. Si alguien te quita una manzana, te quedas sin ella. Si alguien escucha tu idea y la aplica, no te quedas sin ella. Puede aplicarse el verbo “copiar”, pero nunca “robar”. La única manera de robar una idea es que te laven el cerebro para que dejes de tenerla, contra tu voluntad. De esto podría acusarse a emisoras de radio emitiendo machaconamente los últimos singles de ciertos cantantes, pero nunca a usuarios de p2p.

Entonces, si el usuario de p2p no tiene como objetivo robar (quitar) , ¿cuál es su objetivo? Dos cosas, de las cuales la primera es obvia: obtener. Pero la segunda es igualmente importante: compartir (dar). Las redes p2p no funcionarían si sus usuarios no dieran, además de recibir. Además, nadie roba, ya que por mucho que un usuario dé a los demás, no pierde nada de lo que ya tiene. Esto, que es un detalle técnico obvio, es de vital importancia moral. Compartir es algo que requiere cierto esfuerzo, por pequeño que sea. Aunque paguemos una conexión a Internet con el objetivo de obtener del p2p (no de dar), pagar la conexión no es el único coste. Mucha gente deja encendido el ordenador más tiempo del necesario para bajar (obtener) lo que desea, porque quieren subir (dar) a otros. Los ficheros, una vez bajados, ocupan espacio en el disco duro. Sería más cómodo borrarlos nada más bajarlos y verlos, pero mucha gente los sigue sirviendo (dando) aún cuando esto no les aporte beneficios directos. Otro ejemplo más: las conexiones a Internet (al menos en España) son muy asiméticas: permiten bajar información a nuestro ordenador muy rápidamente, pero subir información de nuestro ordenador a otros es comparativamente muy lento. Todos los usuarios de p2p que conozco lamentan este hecho, cuando si su objetivo es simplemente obtener (bajar) y no dar (subir), la asimetría debería serles indiferente. Es más, pensemos en la génesis de un archivo p2p. Un CD de Metallica que acabe en [[es:BitTorrent (protocolo)|BitTorrent]] no empieza su vida allí como un bien que la gente quiere bajar para ahorrarse el comprarlo. Como el lector encontrará obvio, el primer paso, que precede a lo anterior, es subir el CD por primera vez a la red p2p. Alguien compra su CD de Metallica en su tienda de siempre, y al llegar a casa decide compartirlo. Como tiene un bien que le ha producido beneficio (le gusta Metallica) a cambio de una contraprestación (dinero), y como ve que puede repartir ese beneficio a una comunidad amplia (usuarios de p2p) sin perder el bien original (copiar, no robar), se toma su tiempo para subirlo a la red y que todos puedan bajarlo sin pasar por el esfuerzo económico que él tuvo que pasar.

Claro, podría alguien decirme, dar a los demás no produce beneficios directos, pero eso no quiere decir que el usuario de p2p que sube contenidos lo haga desinteresadamente. En primer lugar, los usuarios que no suben nada tienden a recibir menos conexiones de otros usuarios (si yo tengo el capítulo 1 de una serie, y tú el 2, y tú no me das nada del que tienes, probablemente yo no te daré nada del que tengo. Esto lo controla el programa de p2p automáticamente). Además, globalmente es deseable que todo el mundo suba contenidos con fluidez, para que todo el mundo los baje con fluidez. O sea, ¡que no son Hermanitas de la Caridad! (Bueno, las Hermanitas de la Caridad son buenas porque creen en un dios que las condenará al Infierno por toda la eternidad si son malas, o al menos que las premiará más cuanto mejores sean, así que el desinterés es un concepto muy relativo). Precisamente aquí es donde entra la moralidad. El universo p2p es uno en el que el usuario aprende que compartir puede ser beneficioso para todos, el “win-win” que dicen los americanos. Aprende que si te has bajado algo de la comunidad (otras decenas de usuarios que tenían el fichero y lo compartieron contigo), es justo y deseable que tú hagas lo mismo con otros, porque probablemente otros también lo desean. Desde la experiencia personal digo que alguna vez me he bajado algo que he visto mejorable (por ejemplo los subtítulos estaban mal, los nombres de los ficheros estaban incompletos o alfabéticamente desordenados, una peli incluye anuncios…) y he dedicado un tiempo a corregirlo, no solo para mí (que si así fuera, probablemente no valdría la pena el esfuerzo), sino para luego subirlo de nuevo corregido, con la intención de que la gente se baje la versión “buena”. ¿Por qué? Pues porque me sabe mal que todo el mundo tenga que pasar por el mismo trabajo de arreglar el vídeo o lo que sea, si yo con un mínimo esfuerzo (a veces no tan mínimo) puedo solucionarlo para todos. Al fin y al cabo, me gustaría que los demás lo hicieran por mí.

Para mí, este aspecto de que “compartir es bueno”, es una baza moral enorme del p2p. Tras siglos de “tanto tienes, tanto vales”, de “gana dinero, sea como sea” y “si la gente desea lo que tienes, haz que paguen por ello”, y viendo a donde nos ha llevado moralmente, no puedo por menos que alegrarme de ver llegar una tecnología que permite una compartición desinteresada (o interesada porque si yo soy bueno, todo el mundo es bueno, y deseo eso) de bienes. El p2p es un soplo de aire fresco en el panorama de modelos de crear bienestar: gente que hace que otros obtengan bienestar dentro de un esquema en el que ellos también obtienen ese bienestar. Colaboración real, esto es lo que promueve el p2p. ¿No sería genial que esta ideología trascendiese a todos los ámbitos sociales? Y todo esto lo quieren eliminar, para seguir metiéndonos en la cabeza la idea de que si tienes algo que otros quieren, aunque no te cueste nada compartirlo, no debes hacerlo gratis. Que dar sin exigir es malo. En el ejemplo del CD de Metallica de dos párrafos más arriba, quieren convencer al usuario que se compró el CD y lo subió de que si él tuvo que pagar, que paguen todos. Que su generosidad al compartirlo es mala. ¡Que está robando! Y quieren envenenar así la moralidad colectiva de la ciudadanía con la triste excusa de ganar más dinero. No os dejéis convencer, por favor.

Comments (2)

« Previous Page« Previous entries « Previous Page · Next Page » Next entries »Next Page »