Tuesday, April 9, 2013

pyparsing black magic

I really love python and I really hate black magic. Especially when it comes to programming, I hate it when I find solutions I cannot explain... exactly. This is one of those cases.

I've been using pyparsing to make some parsers for at least 3 different types of syntax. Pyparsing is an excellent module that allows you to easily create parsers, based on BnF notation. Each individual parser I made, was eventually working as expected when tested alone. As soon as I tried combining the parsers all hell broke loose. I started getting strange errors from the pyparsing module such as infinite loops and a TypeError with `obj must be an instance or subtype of type`. It felt like one parser 'influenced' the other and I was able to confirm that by changing the order in which they were called. I even made a post to the pyparsing wiki which at this time hasn't been answered.

After much searching I came to the following 'solution'. Most tutorials on pyparsing suggest you import everything from the pyparsing module like so:
from pyparsing import *

Now I remember reading somewhere that this is not a good practice in general and its better to import specific modules or the generic module itself. So, I changed my parsers to just import pyparsing
import pyparsing

Of course I had to start using the full path name for the classes I used but it actually paid off. After I did that everything started working as expected. If anyone can offer a better solution I'm open to suggestions.

Tuesday, February 7, 2012

Translate a quad-dotted decimal netmask to its bit length equivalent

Here's an elegant way of translating a subnet netmask from its quad-dotted decimal representation to a bit length. The initial netmask is represented as a Python list. To get from the string representation to the list just do:

>>> b = "255.255.248.0".split(".")


to get the bitcount just do:

>>> reduce(lambda x, y: x + (y + 1)/32, b, 0)
23


 Modify to taste and njoy

Sunday, September 4, 2011

ΠΩΣΚΑΝΩ - Απλή μετατροπή video απο miniDV σε DVD

Η αλήθεια είναι οτι η κατάσταση που επικρατεί στο Linux με το λογισμικό επεξεργασίας video δεν είναι η καλύτερη. Απο πλευράς σταθερότητας τουλάχιστον. Υπάρχουν αρκετά καλές προσπάθειες (kino, lives, pitivi, cinelerra κλπ) αλλά δυστυχώς ακόμα είναι απλά καλές προσπάθειες.
Η αναζήτηση μου, ξεκίνησε από την ανάγκη να μετατρέψω καμιά δεκαριά κασετάκια miniDV που έχω, σε DVD quality βιντεάκια. Δεν συζητάμε για εφέ (transitions) κλπ.
Η camera μου έχει σύνδεση firewire ή DV όπως λέγεται στην εμπορική. Αφού διαπίστωσα ότι έλειπαν κάποια πακέτα από το gentoo μου, τα εγκατέστησα και ξεκίνησα την περιπέτεια. Ακαιπούσε, επειδή εμείς οι λινουξάδες γενικά είμαστε uber-geeks (μη χ...σω) δεν το λέμε firewire αλλα ieee 1394 ή απλά 1394 (έτσι να το ψάξεις στον πακεταδόρο σου).
Όλα τα links οδηγούσαν στο Kino ως το ποιο ολοκληρωμένο, με δυνατότητα capture από firewire. Με το που το εγκατέστησα και το έτρεξα, βρήκε αμέσως την συνδεδεμένη μέσω firewire καμερούλα μου (καμερούλα μια σταλιά 2x3). Επίσης υποστηρίζει και AV/C (Audio Video Control) οπότε αρχίζει και σταματάει αυτόματα την camera μέσω firewire για να γίνει το capture.

Τι είναι το capture ρωτάς?
Είναι το πρώτο βήμα της διαδικασίας, η μεταγραφή του περιεχόμενο του κασετακίου στο ΠιΣι σου με τις λιγότερες δυνατές απώλειες.
Αυτό γίνεται με το φορμά dv που για standard pal definition έχει ~25Mbps throughput.
Να στο κάνω ταληράκια?
25 MbitsPerSecond = 25/8 = 3.124 MegaBytes Per Second.
Αν λοιπόν το κασετάκι έχει 60 λεπτά βίντεο ήτοι 3600 δευτερόλεπτα, θέλεις:
3.125 x 3600 = 11.250 Gb στο δίσκο. Επί 10 κασετάκια = έχε καμιά 100G να σου βρίσκονται πριν ξεκινήσεις.

Ξεκίνησα να το κάνω  με το Kino αλλά δυστυχώς μετά το δεύτερο κασετάκι μουλάρωσε. Επειδή δεν είχα ούτε την ώρα ούτε την υπομονή άρχισα να ψάχνω κάτι γρήγορο = CLI.
Οι τύποι εκεί στο kinodv είχαν προβλέψει και γιαυτό. Υπάρχει λοιπόν το dvgrab. Πολύ απλό εργαλείο. Βάζεις το κασετάκι στη κάμερα ανοίγεις ένα terminal, φτιάχνεις ένα directory για να αποθηκεύσεις όλα σου τα dv, αλλάζεις σε αυτό το dir και γράφεις:

$ dvgrab --autosplit --rewind --format raw --timestamp cap_

Ταληράκια πάλι: 
--autosplit: Θα το σπάσει σε κομμάτια αυτόματα
--rewind: Γυρνάει πρώτα το κασετάκι στην αρχή (AV/C είπαμε)
--format raw: Γράφει όλα τα δεδομένα όπως είναι αποθηκευμένα χωρίς καμία επεξεργασία.
--timestamp: ΠΟΛΥ βασικό ιδιαίτερα αν είσαι σαν και μένα και δεν γουστάρεις video που γράφουν πάνω ημερομηνία και ώρα (1).
cap_ : Στην ουσία πρόκειται για prefix.

Τα αρχεία που θα προκύψουν από αυτή τη διαδικασία έχουν την ονομασία:
cap_YYYY.MM.DD_HH-MM-SS.dv

Επειδή τώρα τα αρχεία αυτά είναι τεράστια και πολλά μέσα αναπαραγωγής δεν υποστηρίζουν miniDV, αλλά και επειδή θέλεις να δώσεις και κανένα DVD στη θεία, στη γκόμενα ή σε καμιά εφημερίδα, θα πρέπει να μετατρέψεις τα dv σε DVD quality video.
Όταν λέμε DVD Quality μιλάμε για κωδικοποίηση mpeg2 με μέσο bitrate 8Mbps, και ανάλυση 720x576 (PAL).

Περνάμε λοιπόν στο επόμενο βήμα που είναι το πραγματικό video editing. Σε αυτή τη φάση μπορείς να κάνεις παπάδες ΑΝ έχεις όρεξη. Εγώ παραδοσιακά δεν έχω. Το μόνο που θέλω είναι να κάνω τα dv αρχεία που έχουν κοινή ημερομηνία ένα αρχείο mpeg2 με τα παραπάνω χαρακτηριστικά.
Αφού άρχισα με CLI είπα να συνεχίσω. Τι καλύτερο λοιπόν από την ffmpeg. Μιλάμε για τις άπειρες επιλογές. Επειδή όμως όπως είπα βαριέμαι αφόρητα το video editing, το μόνο που θέλω είναι να συνενώσω τα dv με ίδια ημερομηνία και διαφορετικές ώρες.

Η εντολή της ffmpeg για να συνενώσεις πολλά video είναι γενικά της μορφής:

$ cat video1.dv video2.dv ... | ffmpeg -i - ... 

Συγκεκριμένα λοιπόν για την περίπτωση μου, χρησιμοποίησα της παρακάτω επιλογές για την ffmpeg:

$ cat cap_2007.06.03_* | ffmpeg -i - -target pal-dvd -deinterlace 20070603.mpg

cat cap_2007.06.03_* : κάνει globbing στο τρέχων dir και κάνει expand στα ονόματα όλων των αρχείων που θέλω να συνενώσω
-target pad-dvd: Οι μάγκες της ffmpeg (libav) τα έχουν προβλέψει όλα και έχουν έτοιμα προφίλ (targets).
-deinterlace: Αν είναι να παίξει σε flat TV νέας γενιάς είναι must

Το ότι βαριέμαι το έγραψα?

Σιγά μην κάτσω να ψάξω με το χέρι πόσες διαφορετικές ημερομηνίες υπάρχουν στο τρέχων dir. Έφτιαξα λοιπόν το ακόλουθο scriptάκιο για να μου κάνει τη δουλειά.

$ join_and_transcode() { \
      for d in $(for f in cap*;do echo $f | awk -F_ '{print $1}';done | uniq | xargs);do \
          output=$( echo $d | sed -e 's/cap//;s/\.//g').mpg;\
          cat $d* | ffmpeg -i - -target pal-dvd -deinterlace output/$output ; \
      done 
}

Το πρώτο for κάνει loop πάνω στα ονόματα που θα του επιστρέψει το δεύτερο και βγάζει το αποτέλεσμα σε ένα directory output που θα πρέπει να έχει δημιουργηθεί είτε στο τρέχων dir είτε κάπου αλλού κάνοντας την απαραίτητη τροποποίηση.

Αποτέλεσμα της διαδικασίας είναι να μία σειρά από αρχεία με reverse-date notation και κατάληξη .mpg.
Μετονομάστε κατά βούληση και απολαύστε

Thursday, July 21, 2011

ΠΩΣΚΑΝΩ - Εγκατάσταση διαφορετικού JDK/JRE σε CentOS

Πολλές φορές εχω διαβάσει ιστοριές μίσους και έρωτα σχετικά με το πώς μπορεί κανείς να εγκαταστήσει άλλη έκδοση JAVA απο αυτή που παρέχει το σύστημα (που δεν είναι καν java) με τον μηχανισμό των alternatives. Οχι μόνο στο CentOS αλλά και σε άλλες διανομές.

Η απάντηση φίλε μου είναι μία: Μην μπλέκεις.

1. Κατεβάζεις το .bin απο το site της oracle
2. Το κάνεις executable (chmod a+x jre...) και το εκτελείς ή γράφεις (sh jre...)
3. By default εγκαθίσταται στο /usr/java/jre...
4. Αν θέλειες μπορείς να το κανει mv ή να το αφήσεις εκει.
5. Κάνεις edit το script που ξεκιναει την java εφαρμογή σου και δηλώνεις εκει ποιο είναι το JAVA_HOME.
6. Τέλος.

Με τον τρόπο αυτό μπορείς να έχεις 50 javες στο σύστημα σου και κάθε εφαρμογή να παίζει με άλλη java.

Να σου δώσω και ένα παράδειγμα με JBOSS.
1. JBOSS σαν service
Χρησιμοποιείς προφανώς το /etc/init.d/jboss. Κάντo edit και πρόσθεσε κάπου στην αρχή τις εξής δύο μεταβλητές
JAVAPTH=/usr/java/jdk.../bin
JAVA_HOME=/usr/java/jdk...


2. JBOSS standalone
Kάνεις edit το run.conf που βρίσκεται στο bin directory του jboss και πρόσθεσε μόνο την JAVA_HOME μεταβλητή


Στο eclipse επίσης κάνεις edit το eclipse.ini και προσθέτεις το ακόλουθο

-vm
/usr/java/jre...

Ελπίζω να βοήθησα