L'utilizzo del microfono con le API Web Audio è ben descritto qui https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/microphone/
L'utilizzo del controllo WebView in una applicazione UWP è ben descritto qui:
https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlWebView
Se voglio provare ad aprire la pagina del microfono all'interno dell'applicazione UWP devo aggiungere la funzionalità Microfono in Package.appmanifest, ma anche così non funziona.
Il trucco è aggiungere l'evento PermissionRequested al controllo WebView
<WebView x:Name="WebViewControl" PermissionRequested="WebViewControl_PermissionRequested"/>
private void WebViewControl_PermissionRequested(WebView sender, WebViewPermissionRequestedEventArgs args)
{
if (args.PermissionRequest.PermissionType == WebViewPermissionType.Media)
args.PermissionRequest.Allow();
}
mercoledì 27 dicembre 2017
Utilizzo del Microfono in un controllo UWP WebView
venerdì 24 novembre 2017
Il Black Friday ha scassato i maroni
C'è ancora qualcuno al mondo il cui progetto di vita non sia cojonare il prossimo?
mercoledì 6 settembre 2017
Come aggiornare (quasi) facilmente VMWARE ESXi da 5.x a 6.x
Abilitare SSH, spegnere tutte le machine virtuali ed entrare in Maintenance Mode
Da ssh:
Controllare la versione corrente
~ # vmware -lv
VMware ESXi 5.5.0 build-3568722
VMware ESXi 5.5.0 Update 3
Configurare il firewall
Scaricare la lista aggiornata delle versioni
~ # esxcli software sources profile list -d "https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xml" | sort -r
Name Vendor Acceptance Level
ESXi-6.5.0-4564106-standard VMware, Inc. PartnerSupported
ESXi-6.5.0-4564106-no-tools VMware, Inc. PartnerSupported
ESXi-6.5.0-20170702001-standard VMware, Inc. PartnerSupported
ESXi-6.5.0-20170702001-no-tools VMware, Inc. PartnerSupported
...........
-------------------------------- ------------ ----------------
Il sito https://esxi-patches.v-front.de/ contiene informazioni su ogni versione.
Ad oggi l'ultima versione è:
2017-07-27 (Update 1)
Imageprofile ESXi-6.5.0-20170702001-standard (Build 5969303)
Dopo aver googlato per verificare che l'ultima versione sia compatibile con il ferro, procedere con l'aggiornamento
~ # esxcli software profile update -p ESXi-6.5.0-20170702001-standard -d https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xml
Ahi!
Il VIB è il driver per la scheda di rete Atheros interna al PC, ma non ha mai funzionato e ai tempi ho dovuto aggiungere una scheda di rete Intel.
Riprovo dopo aver rimosso il VIB che non mi serve.
~ # esxcli software vib remove --vibname=AR81Family_bootbank_net-atl1e_1.0.1.14
Bene, ha funzionato.
Anzi no, infatti sono stato troppo ottimista:
[InstallationError]
[Errno 28] No space left on device
Questo thread salvifico https://communities.vmware.com/thread/560543 suggerisce di abilitare lo swap a livello Datastore: Manage->System->Swap Edit Settings.
Da Datastore "No" ho impostato un datastore
Riavviato, ripetuto l'aggiornamento e l'update ora ha funzionato
Rimettere a posto il firewall
~ # esxcli network firewall ruleset set -e false -r httpClient
Riavviare il sistema
~ # vmware -lv
VMware ESXi 6.5.0 build-5969303
VMware ESXi 6.5.0 Update 1
I log li visualizzo così: https://IP_of_Your_ESXi/host
La licenza ESXi 5.5 non è più valida e va sostituita con quella per ESXi 6.5.
Infine ho trovato nell'inventario una vm orfana poiché avevo brutalmente cancellato dal datastore la cartella che la conteneva.
L'unico modo che ho trovato per far sparire la voce invalida dall'inventario è stato quello di ripristinare la vm, riavviare il sistema e deregistrare la vm.
Da ssh:
Controllare la versione corrente
~ # vmware -lv
VMware ESXi 5.5.0 build-3568722
VMware ESXi 5.5.0 Update 3
Configurare il firewall
~ # esxcli network firewall ruleset set -e true -r httpClient
Scaricare la lista aggiornata delle versioni
~ # esxcli software sources profile list -d "https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xml" | sort -r
Name Vendor Acceptance Level
ESXi-6.5.0-4564106-standard VMware, Inc. PartnerSupported
ESXi-6.5.0-4564106-no-tools VMware, Inc. PartnerSupported
ESXi-6.5.0-20170702001-standard VMware, Inc. PartnerSupported
ESXi-6.5.0-20170702001-no-tools VMware, Inc. PartnerSupported
...........
-------------------------------- ------------ ----------------
Il sito https://esxi-patches.v-front.de/ contiene informazioni su ogni versione.
Ad oggi l'ultima versione è:
2017-07-27 (Update 1)
Imageprofile ESXi-6.5.0-20170702001-standard (Build 5969303)
Dopo aver googlato per verificare che l'ultima versione sia compatibile con il ferro, procedere con l'aggiornamento
~ # esxcli software profile update -p ESXi-6.5.0-20170702001-standard -d https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xml
Ahi!
[DependencyError]
VIB AR81Family_bootbank_net-atl1e_1.0.1.14 requires
com.vmware.driverAPI-9.2.0.0, but the requirement cannot be satisfied within
the ImageProfile.
VIB AR81Family_bootbank_net-atl1e_1.0.1.14 requires
vmkapi_2_0_0_0, but the requirement cannot be satisfied within the
ImageProfile.
Please refer to the log file for more details.
Il VIB è il driver per la scheda di rete Atheros interna al PC, ma non ha mai funzionato e ai tempi ho dovuto aggiungere una scheda di rete Intel.
Riprovo dopo aver rimosso il VIB che non mi serve.
~ # esxcli software vib remove --vibname=AR81Family_bootbank_net-atl1e_1.0.1.14
Bene, ha funzionato.
Anzi no, infatti sono stato troppo ottimista:
[InstallationError]
[Errno 28] No space left on device
vibs =
VMware_locker_tools-light_6.5.0-0.23.5969300
Please refer to the log file for more details.
Questo thread salvifico https://communities.vmware.com/thread/560543 suggerisce di abilitare lo swap a livello Datastore: Manage->System->Swap Edit Settings.
Da Datastore "No" ho impostato un datastore
Riavviato, ripetuto l'aggiornamento e l'update ora ha funzionato
Rimettere a posto il firewall
~ # esxcli network firewall ruleset set -e false -r httpClient
Riavviare il sistema
~ # vmware -lv
VMware ESXi 6.5.0 build-5969303
VMware ESXi 6.5.0 Update 1
I log li visualizzo così: https://IP_of_Your_ESXi/host
La licenza ESXi 5.5 non è più valida e va sostituita con quella per ESXi 6.5.
Infine ho trovato nell'inventario una vm orfana poiché avevo brutalmente cancellato dal datastore la cartella che la conteneva.
L'unico modo che ho trovato per far sparire la voce invalida dall'inventario è stato quello di ripristinare la vm, riavviare il sistema e deregistrare la vm.
sabato 19 agosto 2017
Copia di file su server remoto senza password
Testato con Ubuntu 16.04.3
Il metodo più semplice e sicuro è usare le chiavi SSH
Verificare che in /etc/ssh/sshd_config sia configurato
PubkeyAuthentication yes
id_rsa è la chiave privata generata con:
La chiave pubblica
$ ssh-copy-id -i .ssh/id_rsa.pub user@server
Una guida molto chiara è qui
Una guida per i server synology è qui e qui
La password mi veniva comunque richiesta e ho tribolato un po' per trovare l'errore.
Prima di tutto ho lanciato il comando in modalità debug
$ ssh -vv -i .ssh/id_rsa user@server
debug2: we did not send a packet, disable method
debug1: Next authentication method: password
Il passaggio successivo è stato consultare sul server il file /var/log/auth.log dove era finalmente riportato l'errore:
sshd[3471]: Authentication refused: bad ownership or modes for directory /home/user/.ssh
Infine
$ chmod 755 /home/user/.ssh
Il metodo più semplice e sicuro è usare le chiavi SSH
Verificare che in /etc/ssh/sshd_config sia configurato
PubkeyAuthentication yes
$ scp -i .ssh/id_rsa source_path user@server:/destination_path .
id_rsa è la chiave privata generata con:
$ ssh-keygen -t rsa
La chiave pubblica
id_rsa.pub
deve essere copiata sul server dentro ~user/.ssh/authorized_keys
$ ssh-copy-id -i .ssh/id_rsa.pub user@server
Una guida molto chiara è qui
Una guida per i server synology è qui e qui
La password mi veniva comunque richiesta e ho tribolato un po' per trovare l'errore.
Prima di tutto ho lanciato il comando in modalità debug
$ ssh -vv -i .ssh/id_rsa user@server
debug2: we did not send a packet, disable method
debug1: Next authentication method: password
Il passaggio successivo è stato consultare sul server il file /var/log/auth.log dove era finalmente riportato l'errore:
sshd[3471]: Authentication refused: bad ownership or modes for directory /home/user/.ssh
Infine
$ chmod 755 /home/user/.ssh
mercoledì 16 agosto 2017
Come individuare la lingua di una stringa in C#
Metti caso che vuoi sviluppare un sistema per determinare la lingua di una frase.
Uno dei metodi migliori sembra essere addestrare un classificatore, ma se i dati di partenza non sono corretti i risultati non saranno soddisfacenti. Un classificatore è un classico sistema Garbage in, Garbage out.
Quindi per sviluppare un sistema per determinare la lingua di una frase potrebbe essere utile disporre di un altro sistema per determinare la lingua di una frase, in modo da filtrare i dati che servono per l'addestramento.
Da Windows 7 in poi si possono usare gli Extended Linguistic Services.
Su NuGet è disponibile un wrapper C# WindowsAPICodePack- ExtendedLinguisticServices
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.WindowsAPICodePack.ExtendedLinguisticServices;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MappingService langDetect = new MappingService(MappingAvailableServices.LanguageDetection);
using (MappingPropertyBag bag = langDetect.RecognizeText("good morning vietnam", null))
{
string[] languages = bag.GetResultRanges()[0].FormatData(new StringArrayFormatter());
foreach (string lang in languages)
Console.WriteLine(lang);
}
}
}
}
Uno dei metodi migliori sembra essere addestrare un classificatore, ma se i dati di partenza non sono corretti i risultati non saranno soddisfacenti. Un classificatore è un classico sistema Garbage in, Garbage out.
Quindi per sviluppare un sistema per determinare la lingua di una frase potrebbe essere utile disporre di un altro sistema per determinare la lingua di una frase, in modo da filtrare i dati che servono per l'addestramento.
Da Windows 7 in poi si possono usare gli Extended Linguistic Services.
Su NuGet è disponibile un wrapper C# WindowsAPICodePack-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.WindowsAPICodePack.ExtendedLinguisticServices;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MappingService langDetect = new MappingService(MappingAvailableServices.LanguageDetection);
using (MappingPropertyBag bag = langDetect.RecognizeText("good morning vietnam", null))
{
string[] languages = bag.GetResultRanges()[0].FormatData(new StringArrayFormatter());
foreach (string lang in languages)
Console.WriteLine(lang);
}
}
}
}
venerdì 23 giugno 2017
Dettatura in italiano con Cortana. Qualcosa si sta muovendo
Finalmente le API di Cortana sono state utilizzate per creare un addin per Word e le altre applicazioni Office.
L'addin si chiama Dictate ed è un progetto Microsoft Garage.
Non solo trascrive, ma anche traduce in decine di lingue.
Una manna per gli antichi come me che si ostinano a usare Word invece di Chrome e Google docs.
Una volta attivato l'addin, Cortana non scrive in Word ma nella finestra correntemente attiva, per cui potreste anche scrivere in Wordpad o Notepad mentre sono in primo piano.
Per ora il grosso limite è che non permette di modificare il vocabolario.
Il sistema funziona benissimo in un contesto generico adatto ai creativi, ma i creativi preferiscono usare la tastiera.
Il vocale viene invece utilizzato da coloro che vengono spremuti sul lavoro per scrivere, che so, referti di TAC al torace piuttosto che relazioni sulle caldaie, ma questi hanno bisogno di un vocabolario tecnico e perciò il sistema in sé è ancora poco utile.
L'addin si chiama Dictate ed è un progetto Microsoft Garage.
Non solo trascrive, ma anche traduce in decine di lingue.
Una manna per gli antichi come me che si ostinano a usare Word invece di Chrome e Google docs.
Una volta attivato l'addin, Cortana non scrive in Word ma nella finestra correntemente attiva, per cui potreste anche scrivere in Wordpad o Notepad mentre sono in primo piano.
Per ora il grosso limite è che non permette di modificare il vocabolario.
Il sistema funziona benissimo in un contesto generico adatto ai creativi, ma i creativi preferiscono usare la tastiera.
Il vocale viene invece utilizzato da coloro che vengono spremuti sul lavoro per scrivere, che so, referti di TAC al torace piuttosto che relazioni sulle caldaie, ma questi hanno bisogno di un vocabolario tecnico e perciò il sistema in sé è ancora poco utile.
venerdì 9 giugno 2017
Come calcolare la frequenza delle parole in un testo in C#
Calcolare la frequenza delle parole in un testo è un problema puramente accademico perché esistono già centinaia di programmi ed esempi di codice pronti per l'uso.
Dovendo comunque scrivere del codice, essendo pigro di natura, sono sempre alla ricerca della procedura più semplice e più breve possibile, ovviamente in C#
L'esempio contempla l'uso delle stopwords
//Testo da esaminare. Ho provato con files fino a 500MB senza attese fastidiose
string text = File.ReadAllText(path, Encoding.Default);
//caratteri separatori che identificano i limiti di una parola
char[] separators = new char[] { ' ', '\r', '\n', ',', '\\', '.', ';', ':', '(', ')', '"', '?', '!', '\'', '-', '«', '/' };
//lista delle parole contenute in text
List<string>words = text.Split(separators, StringSplitOptions.RemoveEmptyEntries).ToList();
//lista delle parole da escludere dal conteggio, le cosiddette stopwords, ad esempio congiunzioni, articoli e preposizioni
List<string>stopwords = File.ReadAllLines("StopWords.txt", Encoding.Default).ToList();
//Rimuove dalla lista le stopwords
//Non è possibili utilizzare Except perché fa una DISTINCT e annulla le frequenze
//Ho trovato molti forum in cui si chiede come utilizzare Contains in modo case insensitive
//O la documentazione è poco chiara o quei post si riferiscono a una versione di .NET antica
//La soluzione è semplice: utilizzare StringComparer
words.RemoveAll(item => stopwords.Contains(item, StringComparer.OrdinalIgnoreCase));
//Infine LINQ per contare le frequenze e presentarle in ordine discendente
var frequencies = words.GroupBy(n => n).Select(n => new { Value = n.Key, Count = n.Count() }).OrderByDescending(a => a.Count);
Dovendo comunque scrivere del codice, essendo pigro di natura, sono sempre alla ricerca della procedura più semplice e più breve possibile, ovviamente in C#
L'esempio contempla l'uso delle stopwords
//Testo da esaminare. Ho provato con files fino a 500MB senza attese fastidiose
string text = File.ReadAllText(path, Encoding.Default);
//caratteri separatori che identificano i limiti di una parola
char[] separators = new char[] { ' ', '\r', '\n', ',', '\\', '.', ';', ':', '(', ')', '"', '?', '!', '\'', '-', '«', '/' };
//lista delle parole contenute in text
List<string>
//lista delle parole da escludere dal conteggio, le cosiddette stopwords, ad esempio congiunzioni, articoli e preposizioni
List<string>
//Rimuove dalla lista le stopwords
//Non è possibili utilizzare Except perché fa una DISTINCT e annulla le frequenze
//Ho trovato molti forum in cui si chiede come utilizzare Contains in modo case insensitive
//O la documentazione è poco chiara o quei post si riferiscono a una versione di .NET antica
//La soluzione è semplice: utilizzare StringComparer
words.RemoveAll(item => stopwords.Contains(item, StringComparer.OrdinalIgnoreCase));
//Infine LINQ per contare le frequenze e presentarle in ordine discendente
var frequencies = words.GroupBy(n => n).Select(n => new { Value = n.Key, Count = n.Count() }).OrderByDescending(a => a.Count);
martedì 23 maggio 2017
Come convertire un file .wav (o un audio qualsiasi) in un filmato .mp4 o un altro formato video
A cosa serve convertire un audio in un filmato?
Non ho trovato altre motivazioni se non caricare un file audio su YouTube.
Ci sono applicazioni desktop e web che già fanno questa conversione, ma se si deve farlo a riga di comando le API di Windows sono di grande aiuto
Ecco il codice di una applicazione console che usa l'oggetto MediaComposition
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Media.Editing;
using Windows.Media.MediaProperties;
using Windows.Media.Transcoding;
using Windows.Storage;
namespace Audio2Video
{
class Program
{
static private string filePath;
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.WriteLine("Usage: Audio2Video");
return;
}
filePath = args[0];
if (!File.Exists(filePath))
{
Console.WriteLine("The file {0} doesn't exist", filePath);
return;
}
Audio2Video().GetAwaiter().GetResult();
}
static async Task Audio2Video()
{
MediaComposition composition = new MediaComposition();
StorageFile inputFile = await StorageFile.GetFileFromPathAsync(filePath);
var audioproperties = await inputFile.Properties.GetMusicPropertiesAsync();
string video = Path.ChangeExtension(filePath, ".wmv");
File.Create(video).Dispose();
StorageFile outputFile = await StorageFile.GetFileFromPathAsync(video);
var backgroundTrack = await BackgroundAudioTrack.CreateFromFileAsync(inputFile);
composition.BackgroundAudioTracks.Add(backgroundTrack);
var clip = MediaClip.CreateFromColor(Windows.UI.Color.FromArgb(0,0,0,0), audioproperties.Duration);
composition.Clips.Add(clip);
var profile = MediaEncodingProfile.CreateWmv(VideoEncodingQuality.Qvga);
// Call RenderToFileAsync
var saveOperation = await composition.RenderToFileAsync(outputFile, MediaTrimmingPreference.Fast, profile);
}
}
}
Non ho trovato altre motivazioni se non caricare un file audio su YouTube.
Ci sono applicazioni desktop e web che già fanno questa conversione, ma se si deve farlo a riga di comando le API di Windows sono di grande aiuto
Ecco il codice di una applicazione console che usa l'oggetto MediaComposition
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Media.Editing;
using Windows.Media.MediaProperties;
using Windows.Media.Transcoding;
using Windows.Storage;
namespace Audio2Video
{
class Program
{
static private string filePath;
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.WriteLine("Usage: Audio2Video
return;
}
filePath = args[0];
if (!File.Exists(filePath))
{
Console.WriteLine("The file {0} doesn't exist", filePath);
return;
}
Audio2Video().GetAwaiter().GetResult();
}
static async Task Audio2Video()
{
MediaComposition composition = new MediaComposition();
StorageFile inputFile = await StorageFile.GetFileFromPathAsync(filePath);
var audioproperties = await inputFile.Properties.GetMusicPropertiesAsync();
string video = Path.ChangeExtension(filePath, ".wmv");
File.Create(video).Dispose();
StorageFile outputFile = await StorageFile.GetFileFromPathAsync(video);
var backgroundTrack = await BackgroundAudioTrack.CreateFromFileAsync(inputFile);
composition.BackgroundAudioTracks.Add(backgroundTrack);
var clip = MediaClip.CreateFromColor(Windows.UI.Color.FromArgb(0,0,0,0), audioproperties.Duration);
composition.Clips.Add(clip);
var profile = MediaEncodingProfile.CreateWmv(VideoEncodingQuality.Qvga);
// Call RenderToFileAsync
var saveOperation = await composition.RenderToFileAsync(outputFile, MediaTrimmingPreference.Fast, profile);
}
}
}
Iscriviti a:
Post (Atom)