
Lorsque j'avais besoin de configurer une archive audio pour un seul site de diffusion, en plus du panneau d'administration, j'avais également besoin d'un lecteur audio. L'émission a duré 40 minutes plus deux pauses musicales. L'utilisation de Waveform dans des formats aussi longs est particulièrement pratique.Par conséquent, comme de nombreux services de musique, j'ai décidé d'utiliser cette solution dans la conception du lecteur.
Avec la future refonte prévue du site et, éventuellement, les futures applications mobiles, la forme d'onde raster reposait simplement contre le coin. Il n'est pas adaptatif, il est extrêmement gourmand en ressources à reconcevoir s'il est dans le raster.
Le célèbre SOUNDCLOUD a résolu ce problème sur de petits écrans en déplaçant toute la forme d'onde par rapport au centre statique. Mais je ne veux pas ça.
La diffusion radio a été effectuée via le panneau d'administration, et j'ai immédiatement fait plus de copies compressées des fichiers audio via ffmpeg. Il serait stupide d'abandonner ses capacités et de générer une forme d'onde.
Algorithme d'actions:
1. Génération d'une forme d'onde dans une taille minimale pour le stockage
2. Traduction en vecteur (JSON)
3. Dessiner un joueur pour ce tableau
4. Mise en œuvre de l'adaptabilité: réduction uniforme de la matrice et retour à l'étape 3
Génération de forme d'onde
Au moment de la mise en œuvre de cette approche, les camarades de la BBC n'avaient pas encore publié
la sortie en JSON
dans leur utilitaire , pour autant que je m'en souvienne. Et pour le moment, je vous recommande de reconstruire leur utilitaire pour supprimer la sortie inutile de nombres négatifs et supplémentaires. Vieux sur les canaux de bitness et autres bêtises.
En attendant, continuez:
Si nous prenons ma conception du lecteur (sa largeur est réduite ici), nous verrons qu'il y a 2 pixels par bande (plus 1 séparateur de pixels). Cela signifie que 600px nous donnera 1200px de largeur.

Je suppose qu'à l'avenir, il sera extrêmement improbable qu'une plus grande présentation du fichier audio soit nécessaire. Eh bien, si vous ne tirez pas le design sur toute la largeur du moniteur 4K, vous devriez y penser, mais je m'arrête à 600x60px.
Et maintenant plus proche du code:
shell_exec("ffmpeg -y -i '$name.mp3' -filter_complex 'aformat=channel_layouts=mono,compand,showwavespic=s=600x120,crop=in_w:in_h/2:0:0' -c:v png -pix_fmt monob -frames:v 1 '$png_path.png' > /dev/null 2>/dev/null &");
-filter_complex - connecte des filtres
aformat - travailler avec le son
channel_layouts-mono - mode mono
-compand est un compresseur et un expandeur. Dans ce mode, les sons faibles et forts seront égalisés en volume, ce qui vous permet d'obtenir une forme d'onde sans pics ni surcharges sur les enregistrements silencieux et forts. La forme d'onde, pour ainsi dire, est toujours étirée au maximum.
-showwavespic = s = 600x120 - s prend la taille de l'image.
-crop = in_w: in_h / 2: 0: 0 - recadrez l'image reçue. En règle générale, la réponse en fréquence de sortie est reflétée autour de l'axe x. Par conséquent, nous saupoudrons, ne laissant que la pointe de l'iceberg.
-c: v png -pix_fmt monob -frames: v 1 - format d'image de sortie, palette de couleurs bw et uniquement la première image (nous n'avons pas besoin d'animation). png8 est idéal pour la qualité (sans perte dans notre cas) / lieu.
> / dev / null 2> / dev / null & envoyer la sortie et les données de travail à l'abîme. Et '&' permet à php de ne pas attendre que la console ait fini de fonctionner, mais de continuer.
En sortie, on obtient cette image:

Taille du fichier final 2.4kb
Ce qui est drôle, c'est qu'il y a quelques années, au lieu du blanc, il y avait une couleur rouge. Les développeurs ont apparemment changé les valeurs par défaut.Convertir la forme d'onde en vecteur
L'image résultante est l'amplitude en Y et le temps en X. Il est élémentaire de la traduire en un tableau JSON unidimensionnel. Où les valeurs agiront comme des valeurs d'amplitude, et le temps est simplement leur indice ordinal.
J'ai décidé de faire la traduction à la volée, sans mettre en cache le résultat, c'est très vite fait.
Nous mesurons le nombre de pixels le long de Y du haut vers le premier, et passons au pixel suivant le long de X.
$a = imagecreatefrompng("test.png"); $i = 0; $h = '60';
Le tableau résultant se compose de 600 valeurs.
[46,28,34,35,34,35,26,33,39,29,29,30,30,30,33,33,28...]
Rendu des joueurs par JSON
Pour une barre de progression de travail pratique, j'ai pris progressor.js d'Elliot Bentley. Il l'a fait pour un service de transcription audio.
github.com/ejb/progressor.js 2,76 Ko
Jetons à nouveau un œil à notre joueur.

La barre de progression se compose de deux couches: un arrière-plan avec des barres grises et vertes.
Ci-dessous, les images sont dessinées avec la fonction getGraph.
Son sens est de dessiner des colonnes de l'épaisseur et de la couleur souhaitées avec des séparateurs de colonnes.
var c = document.createElement("canvas"); c.width = width; c.height = height; var ctx = c.getContext("2d"); function getGraph(fillStyle1,fillStyle2,fillStyle3) { if (fillStyle3) {
Voici un exemple de travail sans adaptabilité4. Mise en œuvre de l'adaptabilité
Maintenant, nous devons réduire le tableau JSON sur le client à la taille souhaitée et vous avez ici l'adaptabilité.
Planifiez un
La toute première méthode qui vient à l'esprit est de supprimer tous les deuxième, troisième, quatrième ... dans un cycle, de sorte que vous ne pouvez pas réduire le tableau de moins de moitié, et la précision des pixels ne peut pas être obtenue ici.
La modification de la forme d'onde en supprimant les valeurs du tableau est une impasse. Lorsque vous faites cela, vous verrez combien la forme d'onde se déchire impersonnellement, car vous lancez des extrêmes et ne faites pas la moyenne des voisins en hauteur.
Nous avons besoin d'algorithmes de rééchantillonnage. Il existe une implémentation de l'algorithme sur js:
plus grandTriangleTroisSeauxIl fonctionne bien, ne demande qu'une entrée comme un tableau, aux indices desquels il recevra les coordonnées XY. Nous avons un tableau unidimensionnel, j'ai donc dû me moquer un peu et refaire la fonction. Cette chose fonctionne comme ceci:

Et
ici, vous pouvez toucher avec adaptative comme KDPV.
Définissez le mode d'affichage où le cadre html sera sur la droite. Ensuite, vous pouvez modifier la largeur de cette fenêtre.
Plan B - Puff
Cependant, je ne voudrais toujours pas charger le côté client. Par exemple, je veux 1000 points-5000, mais toute la largeur de l'écran. Si j'ai plus de points, comment cette chose se comportera-t-elle sur un mobile? D'une part, ce n'est absolument pas un problème, ce n'est pas si cher en apparence, à en juger par les démos de l'algorithme, il mâche facilement 5000 points. Mais d'un autre côté, il faut donner autant qu'on demande. Question de design.
Élémentaire, si vous avez Node.Js, vous pouvez transférer ce code sur le serveur. Et si vous avez php, vous pouvez trouver une implémentation de cet algorithme en php mais ... pourquoi, pensais-je.
Où sont les algorithmes de rééchantillonnage? Dans la même bibliothèque native GD que celle utilisée pour générer JSON. Nous passons simplement le paramètre du client en pixels de la largeur requise et redimensionnons notre forme d'onde avant de la convertir en JSON.
Par conséquent, je développerai le code écrit au début.
$h = 60; $width_new = 600; $a = imagecreatefrompng("$id.png"); $width_old = imagesx($a); $aa = imagecreatetruecolor($width_new, $h); imagecopyresized($aa, $a, 0, 0, 0, 0, $width_new, $h, $width_old, $h); imagetruecolortopalette($aa, false, 2); $i = 0;
Après cela, vous ne pouvez pas vous inquiéter si vous devez modifier la conception, la largeur du lecteur, développer une application mobile. Tout semble assez flexible et très intelligent.
Le code est ici.Oeuf de Pâques.
C'était probablement une journée ensoleillée. La fenêtre de notre chambre donnait sur deux anciens planchers de briques de 9 étages, dont je me souviens étant adolescent, je sais qu'un anneau de tramway s'ouvre derrière eux, un peu plus loin - l'ancien hôpital, il est juste derrière l'école, et le bâtiment actuel avec le bureau où j'essaie de creuser. dans ses mémoires, il s'agit d'un ancien hôpital inachevé, maintenant un immeuble de bureaux purement. Je me souviens comment, dans mon enfance, les forces spéciales se sont entraînées ici, elles ont été montrées à la télévision, prenant d'assaut vigoureusement une structure en béton, envahie par tout ce qui l'entourait. Et maintenant, il s'avère que je choque énergiquement la balustrade brillante, que je descends les escaliers et que j'admire la forme de distorsion de ce bâtiment dans le reflet du complexe résidentiel le plus proche. (À proximité, le long de la ligne de tramway, le mur de l'ancien grand cimetière s'ouvre. Et sur elle est une inscription en peinture verte "Pendant que Boris est au pouvoir" et "Labour Russia". Dieu sait qui et quand ils ont été faits, mais après quelques décennies, ils lisent encore mais restent complètement invisibles. Je n'ai plus vu depuis l'héritage des années 90 un monument plus ancien de la ville.)
Au dernier étage, il est vide, car il se trouve vide dans un paquet avec du sarrasin qui a été commencé: il y a beaucoup de tout en dessous et serré: certains escrocs de géo-intelligence spéciale, bureau 2gis, puis seoshniki régulier, et au-dessus il n'y a presque pas de grains. Pensez-vous que quelque chose devrait pousser à travers les planchers de quelque chose ici, mais au cours des 5 dernières années, seul le lave-vitres a regardé du transcendantal et du comptable immanent aux yeux fous, qui frappent à toutes les portes du sol à la recherche de quelqu'un , qui vous expliquera comment signer un paiement via un plug-in fou pour les services bancaires par Internet en raison d'une autre mise à jour du navigateur.