Détecter des MP3 « tronqués » via sox

Depuis le crash violent de mon disque externe Network (LaCie) en 2012 et une récupération de fichiers dans la douleur, je me retrouvais avec des MP3 « tronqués » : ils faisaient bien leur taille initiale en nombre d’octets, mais à la lecture ils s’arrêtaient brutalement.

Les trier était certes faisable manuellement, mais sur quelques milliers l’opération devient particulièrement..reloue.

Comme tout bon développeur, j’ai trouvé une solution pour que la machine le fasse à ma place 🙂

Via mes contacts, et plus particulièrement Legz, j’ai testé la bibliothèque sox, qui permet de manipuler des fichiers audio (lecture, analyse, etc).

Après 2h de travail (le bash et moi ne sommes pas copains du tout), j’ai pondu ça :

En résumé :
– à l’aide de sox, on coupe le fichier à 0 secondes de sa fin
– vu que sox essaie vraiment d’aller à la fin de ce qui est lisible, sur un MP3 abimé, on a donc un fichier plus court
– on récupère la durée de ce fichier « plus court » et du fichier original, qu’on arrondit
– si la différence est sensible (> 10 secondes), on renomme le dit fichier pour l’identifier par la suite

Essai : http://blog.lahaut.info/2014/12/erreur-proftpd-killed-signal-15-sous-ubuntu-14-04/

Erreur « ProFTPD killed (signal 15) » sous Ubuntu 14.04

Après avoir eu à de nombreuses reprises à relancer un serveur ProFTPD qui s’arrêtait sans raison sur une machine en Ubuntu 14.04, j’ai effectué quelques recherches et trouvé l’article suivant : https://oitibs.com/fix-proftpd-killed-signal-15/, qui donne la solution :

Dans le fichier /etc/init.d/proftpd, il faut changer la commande suivante (autour de la ligne 109, dans la fonction signal() :

start-stop-daemon --stop --signal $SIGNAL --quiet --pidfile "$PIDFILE"

par

start-stop-daemon --stop --signal $SIGNAL --retry 1 --quiet --pidfile "$PIDFILE"

Le problème est lié au fait que ProFTPD se ne se relance pas lors de la « rotation des ses logs » (quand il archive son log actuel pour en créer un nouveau)

Cours « les bases du HTML »

Dans le cadre de cours HTML/CSS que je donne à l’IDRAC, j’ai créé quelques slides reprenant les principales balises et la structure globale d’une page HTML.

cours_htmlC’est assez survolé, mais ca peut vous servir de base pour expliquer le concept.

Elle utilise la bibliothèque Javascript Reveal.js, qui permet, en plus des effets visuels sympas, d’avoir des slides dans les deux directions (donc par exemple de faire des « colonnes » sur un sujet particulier)

Cette présentation est également disponible sur son dépôt Github (sous une licence CC-BY-NC)

Comment bookmarker/mettre de côté des tweets, pour les lire plus tard ?

Il existe sur Twitter la possibilité de mettre un tweet dans les favoris (cette liste est d’ailleurs publique).

Cela correspond à plusieurs usages, et notamment :

  • indiquer à l’auteur du message son soutien, une marque d’attention, dans le même esprit que les « likes » de Facebook
  • mais surtout, « stocker » ces tweets, afin de par exemple les lire plus tard

Pour ce 2e usage, il existe plusieurs services comme Pocket, ou Readibility, mais, outre le fait qu’il faut s’abonner à un service supplémentaire, cela ne s’intègre pas au client que j’utilise sur ma machine principale (TweetDeck pour Chrome). (et à titre personnel je préfère réserver la fonction de favori à des tweets qui me paraissent « importants ».

J’avais vu passer il y a quelques semaines l’annonce faite par Twitter des Custom Timelines, sans réellement en comprendre le fonctionnement.

Il s’agit en fait d’un outil permettant de grouper ensemble plusieurs tweets (qui n’ont pas besoin d’être reliés par un même hashtag, ou de correspondre à la même recherche par mots-clés).

Points positifs

  • on peut y ranger n’importe quel tweet de n’importe quel utilisateur (tant qu’il est visible)
  • ces listes sont intégrables via le créateur de widgets de Twitter dans n’importe quelle page web/article

Points négatifs

  • la dépendance à TweetDeck pour créer les timelines
  • on ne peut donc les créer depuis le site (peut être depuis des clients tiers, je n’ai pas testé)
  • il n’est pas possible de ré-ordonner les tweets dans la liste, le dernier ajouté est affiché en premier

Mode opératoire pour créer une nouvelle « custom timeline »

  • utiliser TweetDeck (sur n’importe quel navigateur), avec vos identifiants Twitter habituels
  • cliquer sur le bouton « Custom timelines » en bas à gauche de l’application :
    tuto_timeline_1
  • cliquer sur « Create custom timeline » :
    tuto_timeline_2
  • saisir ensuite un nom (obligatoire) et une description (ça, par contre, c’est facultatif) :
    tuto_timeline_3
  • enfin, il ne vous reste qu’à y glisser des tweets via la petite icône en forme de croix en bas à droite de chaque message (par un simple glisser-déposer) :
    tuto_timeline_4
  • le menu d’options de chaque timeline vous permet (en plus des options habituelles de filtrage) d’obtenir l’URL publique de cette liste de tweets et le code d’intégration (« embed ») :
    tuto_timeline_5

La custom timeline créée pour cet article est par exemple accessible via l’URL suivante : https://twitter.com/SamyRabih/timelines/418461215505936384

Et si on utilise le code d’intégration fourni (avec les options par défaut), le résultat est le suivant :


Comment obtenir le code d’intégration des « custom timelines » (pour son blog, par exemple) ?

Attention : on ne peut intégrer créer un code d’intégration que pour les timelines créées depuis le compte avec lequel vous êtes connecté(e) (en clair, vous ne pouvez générer le code d' »embed » pour une liste personnalisée d’un autre utilisateur)

A noter : comme tous les widgets Twitter, si vous le supprimez de votre compte, il ne s’affichera plus dans les pages où il a été inséré

« Refresh Blocker » Firefox extension fork

One of my friends was talking me about the « auto meta refresh » of some websites like LeMonde.fr, and I was looking for a way to block it. The RefreshBlocker Firefox extension is the perfect tool for it.

But it displays an annoying notification in the header of the pages :

notification

So I made a fork of this extension, to remove the notification : RefreshBlocker 0.8 (« no notifications » version)

(the original add-on is located on its page on the Firefox plugins website)

Some similar plugin exists for Chrome : Stop AutoRefresh

Non ce blog n’est pas mort

…et pourtant l’envie de l’abandonner m’a plusieurs fois traversé l’esprit.

Une année chargée en émotions, en déceptions et en petits bonheurs.

Inverser la vapeur, essayer de me poser franchement, et de comprendre ce qui sous-tend mon comportement actuel : l’objectif de 2014.

Espérons que ce blog survivra (sans doute, j’ai plein d’idées d’articles en tête, juste une violente fracture de la motivation).

Gérer le drag&drop et le téléchargement de fichiers en Javascript

Depuis quelques temps, il existe au sein de nos chers navigateurs, l’API FileReader, qui permet, comme le résume bien cet article de MDN :

  • de gérer les fichiers sélectionnés via les champs de formulaire « fichier »
  • de supporter le glisser/déposer de fichiers dans le navigateur

Les extraits de code qui suivent sont fortement inspirés de l’article de Maxime Chaillou sur le drag&drop.

On crée tout d’abord une zone qui servira de réceptable à nos fichiers :

<div id="dropfile">Drop your file here to deduplicate SMS</div>

On gère ensuite les évènements sur cet élement :

//Quand la souris, maintenue enfoncée, entre dans la zone, on la colore, pour indiquer l'interaction
$(document).on('dragenter', '#dropfile', function() {
		$(this).css('border', '3px dashed red');
		return false;
});
//Une fois que la souris est rentrée dans la zone, on actualise régulièrement l'état de la zone
$(document).on('dragover', '#dropfile', function(e){
			e.preventDefault();
			e.stopPropagation();
			$(this).css('border', '3px dashed red');
			return false;
});
//Si la souris, toujours enfoncée, ressort, on indique la fin de l'interaction
$(document).on('dragleave', '#dropfile', function(e) {
			e.preventDefault();
			e.stopPropagation();
			$(this).css('border', '3px dashed #BBBBBB');
			return false;
});

Il faut ensuite gérer l’upload à proprement parler :

$(document).on('drop', '#dropfile', function(e) {
	//Si le transfert est possible
	if(e.originalEvent.dataTransfer){
		//S'il y au moins un fichier
		if(e.originalEvent.dataTransfer.files.length) {
			//On bloque l'ouverture du fichier dans le navigateur, ce qui est l'action par défaut
			e.preventDefault();
			//On bloque ensuite la propagation de l'évènement "dépot de fichiers" pour éviter de déclencher toute action sur les éléments parents
			e.stopPropagation();
			$(this).css('border', '3px dashed green');
			//On lance l'upload à proprement parler
			upload(e.originalEvent.dataTransfer.files);
		}  
	}
	else {
			   $(this).css('border', '3px dashed #BBBBBB');
	}
	return false;
});

La function upload() alors utilisée va nous permettre d’envoyer le contenu du fichier déposé à une autre fonction (par exemple pour l’envoyer à un serveur Web) :

function upload(files) {
	var f = files[0] ;
	var reader = new FileReader();

	//La fonction handleReaderLoad est ici associée à l'évènement "onload", pour qu'elle se déclenche une fois le chargement du fichier terminé
	reader.onload = handleReaderLoad;

	//Pour les besoins de cette démonstration, on utilise ici readAsText() qui va lire le fichier sous forme de chaîne de caractères
	//Mais on utilise plutôt readAsBinary, pour l'envoi à un serveur Web
	reader.readAsText(f);            
}

La dernière fonction va quant à elle gérer le fichier à proprement parler (l’envoyer via Ajax, ou, comme ici, traiter la chaîne de caractères comme un XML et en dédoublonner le contenu) :

function handleReaderLoad(evt) {
	var xml = evt.target.result
	deduplicateSMS($.parseXML(xml));
}

Pour cet exemple (qui vise à supprimer les SMS en double dans une sauvegarde XML), on utilise également le plugin jQuery FileSaver.js, qui permet de lancer le téléchargement de fichiers dans un navigateur depuis Javascript :

function deduplicateSMS(xmlSource) {
	var ids = new Array();
	var duplicates= 0;
	var total= 0;
	
	//On explore le XML et on vérifie si la clé de chaque noeud existe déja dans le tableau "ids"
	$(xmlSource).find('allsms sms').each(function(index,e) {
		if (ids.indexOf($(this).attr('address')+$(this).attr('date'))==-1) {
			total+=1;
			ids.push($(this).attr('address')+$(this).attr('date'));
		} else {
			//Si c'est le cas, on le supprime
			duplicates+=1;
			$(this).remove();
		}
	});
	$(xmlSource).find('allsms').attr('count',total);
	//On convertit ensuite ce XML en chaîne de caractères via XMLToString, puis en "Blob" gérable par FileSaver.js
	var blob = new Blob([XMLToString(xmlSource)], {type: "text/xml;charset=utf-8"});
	//On lance ensuite le téléchargement
	saveAs(blob, "sms.xml");
}

La méthode XMLToString utilisée ici est très simple et permet juste de convertir un arbre XML en chaîne :

/* Source : http://www.dotnet-tricks.com/Tutorial/javascript/Y7Q9130612-Convert-string-to-xml-and-xml-to-string-using-javascript.html*/
function XMLToString(oXML)
{
	 //code for IE
	 if (window.ActiveXObject) {
	 var oString = oXML.xml; return oString;
	 } 
	 // code for Chrome, Safari, Firefox, Opera, etc.
	 else {
		
	 return (new XMLSerializer()).serializeToString(oXML);
	 }
 }

Vous pouvez retrouver cet exemple sur Github : https://github.com/samy-r/sms-super-backup-deduplication

Une démo est disponible sur mon espace de test : http://lahaut.info/demos/sms-super-backup-deduplication/

Traduction française actualisée du thème « Adelle » (BluChic)

Ayant récemment eu besoin d’installer le thème Adelle (édité par BluChic), j’ai heureusement trouvé une traduction française, mais celle-ci n’était pas totalement à jour : problème résolu désormais !

Traduction française actualisée du thème Adelle

(merci à WPAddict pour la traduction initiale)

Reprise en main physique #2 : le gainage

Afin de remuscler un peu le pot de Nutella qui me sert de ceinture abdominale, je passe désormais à la phase « active ».

Un de mes amis m’a conseillé une solution simple et sans risque pour le corps : le gainage.

En quoi cela consiste? La position est celle-ci :

images (1)

 

Elle a pour avantage de muscler l’ensemble des zones, sans trop solliciter le dos.

Le rythme à adopter est le suivant :

  • 3 à 5 séries de 10 secondes en contraction
  • puis des séries de 15 à 20 secondes
  • pour ensuite monter jusqu’à des efforts d’1 minute

Je vous ferais un retour dans un des prochains billets sur les effets.

MISE A JOURon m’a conseillé également la version « sur le côté » :

Gainage-des-obliques

Reprise en main physique #1 : trajet Part-Dieu – Gorge de Loup en Vélo’v

Puisque j’ai enfin décidé de faire attention à ma carcasse, une des premières étapes est de faire de l’exercice.

Un moyen très simple est le vélo, et le trajet domicile-travail (6km) permet de commencer sereinement sans trop exagérer.

Durée du trajet : 45 minutes

Trajet suivi :

  • Cours Lafayette de Part-Dieu jusqu’à Cordeliers
  • Rue de la République
  • Quai Pierre Scize
  • Quai Arloing
  • Rue Sergent Berthet

Bilan rapide : ca se fait assez tranquillement, mais je suis un peu rouillé 🙂

Points positifs :

  • Trajet quasi plat
  • Site propre sur une grande partie du chemin

Points négatifs :

  • Forte pollution sur le Cours Lafayette
  • Tomettes sur le Cours Lafayette qui rendent la conduite assez désagréable
  • Faux-plats un peu vicieux

Notes pour plus tard :

  • Prévoir des gants très légers (plutôt pour couper le vent que pour avoir chaud)
  • Bien s’hydrater après

Trajets aller (A-B) et retour (B-C) :

Agrandir le plan