Showing posts with label accessibility. Show all posts
Showing posts with label accessibility. Show all posts

Sunday, September 1, 2013

Extending jQuery selectors and facing conflicts with querySelectorAll

You know that is possible to extend the jQuery selector capabilities?
Just type...

$.expr[':'].foo = function(element) {
    ...
};
... and this function will be called when :foo selector is used.
Nothing new on this side.

Recently I started working on a new jQuery plugin and to make things simpler I needed to find a way to override an existing jQuery selector. Again: nothing new; some years ago I found that the method described in the article above can be also use for override, and not only for extend.
To make things more testable I decided to move this behavior into another (separated) jQuery plugin, which is the argument of this post.

When I used this method again nowadays I found unexpected results.
I was looking a way to change the way :checked and :checkbox selectors work, so I defined...

$.expr[':'].checkbox = function(element) {
    ...
};
...and...
$.expr[':'].checked = function(element) {
    ...
}; 
This is what I found:
  • :checkbox was working as expected
  • :checked was not working as expected
In facts, the :checked selector was only working when using it inside a .filter() call.
I'm not a jQuery core expert, I never looked at it's code very much, but this time I needed to investigate my problem. Also: I need to make this work on jQuery 1.7 and more modern 1.10 version, and codes are quite different.

Here what I found: both jQuery versions contains a method for capturing the :checked selector, but it's only called when you call filter() (so here my override attempt works as expected). For normal selectors jQuery now heavily relies on native querySelectorAll API for every browser that is supporting it.

This is the core of the problem: the :checkbox selector is a non-standard ones (not defined by any CSS specifications) while :checked is a know CSS selector. So browsers that support the :checked selector for querySelectorAll are calling this native API.

This is someway hilarious! While querySelectorAll are making our browser (and jQuery usage) faster, it's lowering jQuery extensions capabilities.

I found no smart way to change how querySelectorAll works (and probably there's no way at all, I think we are at C compiled code level here).
The trick I used is to disable the native querySelectorAll when the selector contains :checked, and in that case call my jQuery version instead.
How?

    var pattern = /\:checked/;
    if (document.querySelectorAll !== 'undefined') {
        // need to partially disable querySelectorAll for :checked
        document.nativeQuerySelectorAll = document.querySelectorAll;
        document.querySelectorAll = function(selector) {
            if (pattern.test(selector)) {
                throw('Native ":checked" selector disabled')
            }
            return this.nativeQuerySelectorAll(selector);
        }
    }

The first step is to disable (keeping a "backup") querySelectorAll, changing it with a custom function. Then all I need to do is check if the :checked selector is used somewhere in the query. If not: just call the backed up querySelectorAll, but if it's called somewhere I simply need to raise an exception.

This is the interesting part I found looking at the jQuery source: jQuery core try to use querySelectorAll every time is possible, switching to internal JavaScript code only when it's not supported. In this way I'm simulating the fact that my modern browser is not supporting :checked selector for querySelectorAll.

Problems

I found this experiment interesting, but there's some things I don't like:
  • I'm disabling the native querySelectorAll usage also when it's basic features are enough (i.e: if I really need to load only checked checkboxes and not other fancy stuff)
  • I'm wrapping every querySelectorAll calls inside the selector check, making all calls to querySelectorAll slower
  • I want only to extend jQuery here, but I'm also disabling all native querySelectorAll calls if the query containes ":checked"
  • I'm changing how JavaScript works. This is calling me back to times when I used prototype.js (that I never liked)
Any suggestion for a better code way are welcome!
This is the result of the experiment: jQuery WAI ARIA Compatible Checkbox Plugin.

Off-topic

Apart the problem described in this article, I let's spend some words on the "new" jQuery Plugin Site. Last time I published a jQuery plugin (lot of time ago) this site was a total mess: you need to authenticate, upload source tarball, write documentation on a wiki-like page, ...

I really liked how it works now: if you want to publish a plugin, just put it on GitHub and configure a commit hook! Simple and amazing!

Friday, January 6, 2012

Tabindex: handle focus and JavaScript events on every elements

My last reading (still in progress) is a book about JavaScript: "JavaScript Cookbook" (Shelley Powers - O'Reilly). It's full of very interesting chapters (probably it will feed many future article here).

Today I will talk about a JavaScript behavior learned in one of the examples found in the book, related to JavaScript events inside Web pages.

Types of usable event
Using pure JavaScript, not all existing events can be used on every page elements. For example: one of the first things I liked when I started using jQuery year ago was the possibility to use onclick event for whatever DOM page element, also in Internet Explorer (that commonly dosn't allow this event to be fired for all types of element).

The example I found in the book talks about another event: onkeypress.
What kind of elements can react to this kind of event? Commonly only elements able to take the focus (like links, but more common are form elements like textarea of input).
The example shows how using another uncommon JavaScript attribute we can change this behavior, enabling all other page elements. I'm talking of tabindex attribute.

How to use tabindex
As I'm mainly a Plone programmer, when tabindex was removed from all templates of the CMS (don't remember exactly, but I think it was when Plone 3.0 was released) I was happy. Why? Because tabindex is commonly not needed in a well-designed Web page.

The tabindex attribute define the order in which a user navigate the page using the keyboard (the TAB /SHIFT+TAB key) but if you define the order of your DOM elements in a logical manner you will simply not need this attribute. However note that it is not deprecated:
  • Some non-common pages can need this attribute to force the navigation first to a page section that isn't at the top (to be honest, I can't find a simple example of this)
  • A value of tabindex of "-1" make an element, commonly navigable using keyboard, not accessible anymore.
See this good tabindex reference for more details.

Now the great tabindex magic I learned: when tabindex is used on a DOM element (with a value of 0 or more), it magically gain the power of obtain focus.

Let see some examples.
Please note:
  • I tested examples with Firefox, Opera, Chrome and Safari, on MacOS. With older Internet Explorer versions you probably need some fixes in event handling.
  • If you are on MacOS, use Chrome because the keyboard navigation with TAB is a mess. See below for more on this.
The first example is a simple HTML page with 2 links, one paragraph, and where onclick and onkeypress on those elements raise simply an alert message (the text inside the node).

<html>
<head>
<script type="text/javascript">
<!--
window.onload=function() {

    var handleAction = function(event) {
        alert(this.innerHTML);
    }

    var p = document.getElementById('foo');
    p.onclick = p.onkeypress = handleAction;

    var links = document.getElementsByTagName('a');
    for (var i=0;i<links.length;i++) {
        links[i].onclick = links[i].onkeypress = handleAction;
    }

}
//-->
</script>
</head>

<body>
    <a href="javascript:;">Link 1</a>
    <p id="foo">
        Test here!
    </p>
    <a href="javascript:;">Link 2</a>
</body>
</html>
First of all the mouse event: you will be able to click on both links and the paragraph (not sure of this in all IE versions as I'm not using jQuery there).

Now let's try the keyboard navigation. Using the TAB you will be able to move only onto link elements. When one element get the focus, clicking a key you will get the same message you get for a mouse click.

If you look at the code you'll see that I'm trying to register the onkeypress event also on the HTML paragraph, but it is ignored.
This is right: a world where every DOM element can get the focus will make keyboard navigation painful. But: how can I do if I really need that a single DOM element (commonly not focusable) could take focus and keyboard events?

This is where tabindex help. If you look at the second example you will see that the only difference is the use of tabindex on the P node.
<html>
<head>
<script type="text/javascript">
<!--
window.onload=function() {

    var handleAction = function(event) {
        alert(this.innerHTML);
    }

    var p = document.getElementById('foo');
    p.onclick = p.onkeypress = handleAction;

    var links = document.getElementsByTagName('a');
    for (var i=0;i<links.length;i++) {
        links[i].onclick = links[i].onkeypress = handleAction;
    }

}
//-->
</script>
</head>

<body>
    <a href="javascript:;">Link 1</a>
    <p id="foo" tabindex="0">
        Test here!
    </p>
    <a href="javascript:;">Link 2</a>
</body>
</html>
However, the behavior difference is big.
You can try again the page with keyboard navigation with all browsers used before (again: I suggest to use Chrome if on MacOS).

Now you are able to give the focus to the paragraph! Also, keyboard event is now raised on the paragraph. You probably get the point...
Tabindex attribute can make focusable whatever element of the page and you are able to use keyboard events on them.
Isn't this great? I think that could be helpful sometimes.

Browsers differences (AKA: MacOS hate TAB)
Let's change the article focus.
Testing example one and two with all defined browsers shown some different behavior.
The tabindex definition says that element with tabindex are the first that take the focus (from the lower value to the upper), keeping the DOM order when values are equals; only then, all other focus capable elements are traversed (still, using the top-down DOM order).

For a reason I never deepen, on MacOS (but workarounds can be found on the Web) only form elements seems able to take focus (links not). Also with Firefox, that on other Linux/Windows environment works like a charm, I can't put the focus on links.
The only tested browser on MacOS that works as expected is Chrome, however also Chrome does something unexpected: if you test the second example you will see that the DOM order are kept (while the tabindexed ones must be the first).

But example 2 works also on other browsers on MacOS: you are able to put the focus using TAB key onto the paragraph.
So you can think "I can try to put a tabindex on every DOM page element I want to be accessible using keyboard to fix this MacOS problem".

If you test example 3 (that put "tabindex=0" also on A elements) you'll that this is false. Still, links are not accessible using keyboard. Strange...

Sunday, March 27, 2011

I video in Plone: come (e nel modo giusto)

Il Web è cambiato molto, ce ne siamo accorti? Quello che una volta era una collezione di testi collegati tra loro, oggi porta tante altre tecnologie, canali di comunicazione (media) e funzionalità. Nemmeno le immagini sono più sufficienti, e il fenomeno YouTube credo ne sia in gran parte responsabile (se così si può dire).

Se quindi i video diventano, in modo ufficiale, parte dei contenuti del Web e molto spesso il contenuto stesso, tanto vale prendere in considerazione la possibilità che il nostro CMS preferito li supporti!

NB: nel seguito ometto volutamente l'argomento HTML 5, che probabilmente nei prossimi anni semplificherà l'argomento audo/video per il Web ma ad oggi è ancora prematuro.

I video in Plone
Se la necessità è integrare un nuovo tipo di contenuto in Plone o poter vedere un video all'interno di un contenuto Plone, lo standard de facto è usare collective.flowplayer.
Questo prodotto si basa sul diffuso player open source Flowplayer e si installa facilmente in Plone, fornendo alcune funzionalità semplici ma efficaci.

Che cosa fa? In modo intelligente trasforma i file inseriti in Plone (se in uno dei formati compatibili col player) in veri e propri video riproducibili dal Web. La stessa cosa viene fatta anche con i contenuti di tipo Collegamento (ma questa seconda funzionalità la trovo di più raro utilizzo... si tratta di inserire un URL ad un file compatibile).
Altra funzionalità e permettere, previa qualche configurazione, la possibilità di inserire i video all'intero dell'editor WYSIWYG di Plone.

Credo che di articoli di blog su questo prodotto ne siano stati fatti vari, quindi non è mia intenzione soffermarmi oltre, ma prima chiariamo questo punto: ci sono alternative? Altri player video? Ovviamente sì, ma Flowplayer è il più diffuso: funziona bene e forse (ma spero in minima parte) il fatto che...
  • il creatore originale sia Martin Aspel
  • il creatore di Flowplayer sia anche il creatore delle jQuery Tools, che sono il framework per le interfacce grafiche in Plone 4
...influiscono sulla scelta.

Formati dei video
Avete mai trovato difficoltà nello spiegare ai vostri utenti come non tutti i formati video siano amici del Web? Flowplayer supporta i formati mp4 e flv. Il DivX formato AVI della comunione di vostra nipote non è propriamente un buon formato...

Nel caso quello sia l'unico formato disponibile potete usare un programma di conversione. Ma cosa fare se tutti i video che devono essere allegati partono da un formato incompatibile? Spiegare al redattore come usare un ulteriore software per fare la conversione non è mai un buon modo... la fotocamera dell'utente gli genera un file mpeg. Se non si vede su Web sembra sempre colpa di Plone!

Esiste almeno un prodotto Plone per eseguire la ri-codifica live del video. Installando collective.transcode.star avrete disponibile nel vostro buildout un nuovo demone che si occuperà di convertire i vostri video! Fantastico!

Limiti
Anche se la strada sembra spianata, ci sono alcuni limiti (o potenziali problemi) nel gestire i video in Plone.

Innanzi tutto va tenuto presente come un video sia prima di tutto un "grosso" file. Quando il browser remoto inizia la visione del video (per meglio dire, durante il buffering) il file si muove attraverso la rete. Un video in formato flv può comunque occupare centinaia di megabyte.

Questo porta a qualche problema.

Consumo della memoria
Nelle versioni di Plone precedenti alla 4.0 (non se si è installato a parte anche plone.app.blob) il caricamento da parte di Plone di un file porta anche al caricamento completo dello stesso, che viene messo nella memoria cache del thread che ha servito la richiesta. Per fortuna plone.app.blob evita questo problema (anche su Plone 3).
Anche altri prodotti come FileSystemStorage danno lo stesso beneficio, ma se potete scegliete i blob nativi di Zope.

Lock dei thread di Zope
In una installazione standard di Plone, l'application server sottostante (Zope) è configurato per gestire al massimo 4 thread concorrenti nel servire le richieste degli utenti.

Fintanto che il file intero non viene inviato, quel thread è bloccato nel servire la richiesta. Questo vale sia per l'upload del video che per la sua visualizzazione. L'aumento del numero dei thread non è una soluzione (meglio avere più istanze di zeoclient... ma dovete avere le risorse adeguate).
Questo problema è potenzialmente grave se volete usare Plone pesantemente per la gestione dei video.

Una soluzione, che scarica completamente Plone dal problema di lettura del blob e che quindi si integra con plone.app.blob introdotto sopra, è l'uso di ore.bigfile, introdotto da un ottimo articolo di Aaron VanDerlip. Questo è da tenere presente anche se non state gestendo video in particolare, ma solamente grossi file.
Per riassumere in due parole, questo prodotto sfrutta il Web server Apache (che di solito viene messo davanti ad ogni sito Plone) per lasciare completamente a lui la gestione dell'invio del video (anche in upload). Plone viene solo interrogato per check di sicurezza, poi il file blob viene preso e mandato a client che ne ha fatto richiesta.

Pare purtroppo che questo prodotto non sia rilasciato. Il grado di maturità quindi non è ben chiaro... :-(

EDIT. Da un commento, mi sono accorto che questo pezzo non è stato ben scritto. In Realtà plone.app.blob risolve anche il problema del lock del thread Zope pur non facendo nulla di speciale... Zope ha un modo efficiente di servire questo tipo di situazioni da moltissimo tempo (non ricordo, ma forse addirittura dalle versioni di Zope precedenti all'era Plone), ma per qualche motivo questo metodo non è così ben documentato e noto.

import os, stat
from ZPublisher.Iterators import filestream_iterator

def download(self):
filepath = '/home/me/VeryBigBigFile.pdf'
size = os.stat(filepath)[stat.ST_SIZE]
self.REQUEST.RESPONSE.setHeader('Content-Length', size)
return filestream_iterator(filepath, 'r')
Cosa succede? Quando nella response viene inserito un oggetto filestreamiterator, Zope sa che deve servire in modo efficiente la lettura della risorsa. Non ricordo i dettagli del funzionamento ma fondamentalmente la lettura viene gestita con un thread separato, e quello di Zope viene quindi subito liberato.

Quindi? Tutto ok?

A mio avviso questo non significa che coi BLOB abbiamo risolto tutti i problemi per rendere Plone la "Uber-Applicazione" di streaming. Come ho detto sopra, ogni istanza Zope è fatta di thread, che quindi vengono eseguiti all'interno dello stesso processo Zope (se non capite bene di cosa parlo, leggete cosa dice Wikipedia).

Un nuovo thread aumenta il lavoro totale che viene fatto dal processo. Ricordate quando sopra dicevo che l'aumento del numero di thread non è quasi mai una soluzione? Il problema è che se la vostra istanza Zope viene eseguita su una supermacchina in stile Multivac, con vari processori multicore, l'istanza (il processo) viene eseguita comunque da un processore. Più istanze (zeoclient) e uno zeoserver invece usano processi (e, se disponibili, processori) diversi.

Per tornare ai nostri blob: il thread non viene bloccato, ma il nuovo thread rende "tutto più lento".

Perché l'approccio di ore.bigfile è migliore? Perché Apache è un'applicazione che nativamente usa processi separati. Far servire il file direttamente ad Apache:
  • fa sì che il file non passi, neanche in minima parte, per l'area di memoria del processo Zope
  • non aumenta il carico dell'istanza con un nuovo thread
  • sfrutta Apache, in un processo separato.
Consumo della banda
A questo problema non c'è una soluzione pratica e spesso viene dimenticato. Il cliente vi chiede "voglio i video in Plone", ma non ci si ferma a pensare che se questi video hanno successo, è la banda disponibile al vostro sito a risentirne se decine di persone iniziano a guardare i vostri bellissimi filmati. Questo comporta che:
  • i video si vedano male (i video "scattano")
  • la navigazione del resto del sito ne risenta (il sito va lento)
  • l'attività dei redattori del sito ne risenta (il sito va lento)
Non sottovalutate mai l'opportunità di mettere i vostri video da "un'altra parte", su servizi che questo lavoro lo fanno di mestiere. Esempio?
  • YouTube
  • Vimeo
  • ...
Se un account "gratuito" su questi servizi non vi pare sufficiente, valutate anche cosa comporta spendere una piccola somma per comprare un account premium... siete certi che il gioco non valga la candela?

Video esterni: e adesso?
La cosa più semplice in assoluto è configurare Plone per consentire ai vostri redattori di inserire il codice HTML necessario per eseguire l'inclusione del video del sito remoto (teniamo come esempio principale YouTube, ma la cosa vale per qualunque altro servizio).

Dovete configurare i filtri HTML di Plone per non considerare più "cattivi" alcuni tag HTML usati per questo tipo di soluzioni: i tag sono di solito EMBED e OBJECT.

Filtri Html in PloneQuesto viene fatto dal pannello di controllo di Plone, nella sezione di gestione "Filtri HTML".

NB: c'è un motivo valido, di sicurezza, per cui Plone di base non permette agli utenti di poter usare questi tag... un redattore potrebbe inserire codice malevolo nelle vostre pagine!

Come detto precedentemente la documentazione di collective.flowplayer affronta anche questo argomento. Se siete interessati

Un altro interessante approccio piuttosto recente è un prodotto sviluppato da Quintagroup per interfacciarsi con i servizi di embed.ly.
Usando collective.embedly il codice per l'integrazione con i video remoti viene generato in un modo semplice, non dipendente dalla piattaforma scelta (e ne sono supportate varie) e usando TinyMCE! Del codice Javascript al momento del rendering della pagina "trasforma" i link marcati nel player video corretto! Questo elimina anche il problema di abilitate i tag potenzialmente pericolosi in TinyMCE!
Notevole, ma solo per Plone 4.

Ancora video esterni... ma pur sempre contenuti
Il limite di inserire video esterni nei modi descritti sopra è che il video diventa parte di un contenuto ma non è un contenuto. Non possiamo taggarlo o associargli gli utili metadati che abbiamo in Plone. Non possiamo fornire ai nostri utenti una collezione di video... questo potrebbe essere un grosso limite per la parte redazionale del vostro sito.

Quindi? L'unica soluzione è avere la banda? Non esattamente. In RedTurtle ad esempio abbiamo sviluppato un prodotto, redturtle.video, che fa di nuovo dei video un contenuto. Il prodotto segue espressamente una specifica richiesta di un cliente ed è composto da due contenuti: il tipo "Video Interno" e il "Link a Video".
Mentre il primo è tutto sommato un semplice contenuto costruito sulle funzionalità già date da collective.flowplayer (ma faccio notare una questione di usabilità non da poco: non è semplice capire che per creare un "video" in Plone un utente dovrebbe inserire un "file", come invece è nel funzionamento di collective.flowplayer... l'utente si aspetta che nel menù di aggiunta element ci sia "Video") voglio evidenziare ciò che viene dato da contenuto di tipo link.
In minima parte è, di nuovo, un contenuto costruito su qualcosa che da collective.flowplayer, ma fa anche altro: un po' come collectve.embedly si integra con siti esterni che forniscono servizi video, ma tramite un contenuto simile al link. L'utente inserisce un link a YouTube, oppure Vimeo, e di nuovo abbiamo il nostro player integrato (e tag, correlati, etc...).

Altri prodotti
Prima di cambiare rotta con un argomento parallelo, voglio fare notare come le suite di prodotti nel mondo di Plone non si limitano al solo collective.flowplayer.
Eccone altri:
  • Plumi. Praticamente trasforma Plone in un CMS per i Video. Se il vostro target è creare un sito il cui documento principale sono i video, valutate seriamente questo prodotto!
  • Plone4ArtistsVideo. Storicamente è stato il primo prodotto che si è occupato di video... funziona ancora... ma il Web è pieno di persone che si sono pentite di averlo installato.
  • Plone Video Suite. Progetto interessante e di buone intenzioni. Nasce da alcuni sprint che volevano portare ordine nel caos della situazione video in Plone (probabilmente il ruolo di Attila in questo caos lo ha fatto P4A Video :-().
    Purtroppo ad oggi non si sa a cosa porti questo progetto.
La panoramica sui prodotti video è finita, ma vi pare poco?

Per quanti riguarda l'accessibilità
Per chi come me l'accessibilità dei siti Web non è solo un'abitudine, ma una necessità quotidiana nel lavoro, sa come inizialmente i requisiti della Legge Stanca (Legge 4/2004) possano a volte sembrare limitanti in maniera piuttosto stringente. In realtà, sebbene sia una legge lungi dall'essere perfetta (e per chi ha lavorato con Plone sa bene cosa significhi il Requisito 1, relativo al codice HTML/XHTML Strict) è comunque una legge "giusta".

Un sito accessibile è quasi sempre un sito ben costruito, e non solo da un punto di vista strutturale, ma anche umano. Sapendo che il sito sviluppato ha tenuto conto, magari anche solo in minima parte, di utenti non vedenti, non udenti o ad altre forme di disabilità dovrebbe farci sentire meglio.

Ecco gli "obiettivi e finalità" della Legge:
La Repubblica riconosce e tutela il diritto di ogni persona ad accedere a tutte le fonti di informazione e ai relativi servizi, ivi compresi quelli che si articolano attraverso gli strumenti informatici e telematici.
Se per quanto detto fin'ora il nostro sforzo è che i video diventino contenuti, i video devono essere accessibili. Ci sono ovviamente requisiti tecnici specifici riguardanti i video e i contenuti multimediali nella Legge Stanca, ma chiediamoci prima di tutto come un video può essere completamente accessibile.

Quali difficoltà ci sono nell'accesso ad un video sul Web?
  • Accessibilità dei comandi del video a tutti i dispositivi di input
  • Accesso ai contenuti del video a soggetti non vedenti
  • Accesso ai contenuti del video a soggetti non udenti
  • Accesso ai contenuti del video a soggetti non udenti e non vedenti
Molto di quello che leggere di seguito viene dalla lettura dell'ottimo libro di Michele Diodati: "Accessibilità - guida completa".

Accessibilità dei dispositivi di input
Non esiste solo il mouse, anzi: fingiate esista solo la tastiera! Questa regola non vale solo per i video ovviamente, ma per i contenuti Web, Plone in proposito fa già un ottimo lavoro.
Per l'accesso al video l'attenzione si sposta sul player usato.

Le ultime versioni di Flowplayer dovrebbero aver migliorato la situazione. Uso il condizionale perché non ho avuto esperienze dirette di recente, ma ho solo letto i commenti degli autori alle ultime release.

Tempo fa, essendo rimasto piuttosto affascinato dal mondo dei plugin che girano attorno a Flowplayer, ho sviluppato un prodotto Plone, collective.flowplayer_toolbar, che sfrutta le funzionalità di uno di questi plugin: il plugin della barra di controllo.
Questo prodotto funziona bene anche con le versioni recenti di Plone e collective.flowplayer, quindi nel caso qualcosa nell'accessibilità della barra di controllo Flash non vi piaccia, potete pur sempre usare questo! :-)

Audiodescrizione dei video
E' l'argomento che conosco meno, quindi passerò oltre in fretta.

L'audiodescrizione si occupa dei soggetti non vedenti o ipovedenti. Non fermatevi a questa frase pensando che se il vostro video ha una traccia audio basti il sonoro del video stesso... questo può essere vero per alcuni tipi di filmati (mi permetto di dire a istinto che per un video contenente un'intervista non sia necessaria nessuna descrizione aggiuntiva), ma non è una regola generale.
L'audiodescrizione è un'ulteriore traccia audio che si sovrappone alla prima (ovviamente, senza inficiarne la comprensibilità) e che commenta, magari nelle pause del testo parlato, che cosa succede a video. E' l'audio per le scene dove l'audio non è sufficiente a capire cosa succede.

Non conosco le caratteristiche tecniche sul come realizzare un'audiodescrizione ma credo sia la cosa più complessa da fare per rendere un video accessibile, sia dal punto di vista del tempo investito che per la tecnologia richiesta (soprattutto se il video ha già in effetti una sua traccia audio).
Potrei sbagliare, e nel caso vi invito a correggermi.

I sottotitoli del video
Per qualche motivo più diffusi e conosciuti al grande pubblico (forse siamo tutti figli della pagina 777 di televideo), chi beneficia dei sottotitoli sono soggetti non udenti o in generale con disabilità all'udito che non permettono loro di comprendere i suoni e il parlato.

La soluzione a questo tipo di disabilità sono appunto i sottotitoli. La sottotitolazione di un video è più semplice dell'audiodescrizione, forse perché è più semplice anche da comprendere che cosa va scritto effettivamente scritto.
Le risorse sono anche più diffuse, cito ad esempio l'interessante progetto Universal Subtitles.

Tornando al nostro compagno collective.flowplayer, esiste un ulteriore plugin di Flowplayer per poter visualizzare i sottotitoli nei video: il captions plugin.
Ancora una volta la sua integrazione con Plone è stata piuttosto semplice: lo sviluppo di collective.flowplayercaptions non ha richiesto enormi sforzi se non comprendere bene le API del plugin (piuttosto confuse) e creare un'integrazione non troppo invasiva per i file Plone.

Questo prodotto non fa tutto: è comunque il redattore che deve fornire il file contenente i sottotitoli (supportato è il formato RST).

Il costo in termini tecnologici per ottenere i sottotitoli e basso, ma c'è un certo sforzo in termini di tempo.

La trascrizione testuale del video
La trascrizione video è l'alternativa dove cadono tutti quelli che vogliono tentare di rendere il proprio sito accessibile. E' già qualcosa, ma non si potrebbe fare di meglio.

Chi beneficia della trascrizione video è l'utente sordocieco, che per ovvi motivi non può trovare né beneficio dall'audiodescrizione né dai sottotitoli.
Con la completa trascrizione del contenuto del video, compresi di dialoghi e descrizioni, può invece (sempre attraverso dispositivi hardware specifici) "leggere" il testo scritto tradotto in Braille.

Dal punto di vista tecnico, Plone può fornire una trascrizione testuale ad un video tramite un semplice contenuto correlato, magari ad una semplice pagina. E' ovvio che il redattore deve inserire nel CMS questo documento, ma la sua realizzazione spaventa meno che non fornire un'audiodescrizione o un supporto ai sottotitoli. Per di più si potrebbe pensare "se con questa alternativa supero ben due disabilità, tanto vale limitarsi a questa"! Vero... ma non molto giusto.

E' ovvio che un utente non udente o un non vedente possono accedere beneficiare della trascrizione testuale, ma l'esperienza vissuta è assai limitata. A questo punto perché non rimuovere il video per tutti e fornire solo le trascrizioni?! Vi piacerebbe?

Accessibilità delle risorse esterne
Risolvendo un problema, ne introduco un altro. Possiamo sentirci tranquilli se un video preso da YouTube e inserito nel nostro sito Plone non è accessibile? Dopo tutto la colpa è di YouTube, giusto?

Questo scaricabarile non dovrebbe farci sentire meglio, e per un ente pubblico questa non può essere una scusa valida. Rendere anche i video presi da YouTube (e probabilmente da altri servizi) accessibili si può, ma richiede uno sforzo aggiuntivo.

Un documento con vari interessanti spunti è "Captioning YouTube Video and Providing Accessible Controls".

Conclusioni
I video in Plone, integrati o inseriti come contenuti, sono possibili, che sia un semplice video di pochi secondi ad un intero sito dedicato ai contenuti multimediali.

L'accessibilità dei video è una sfida reale. E' possibile, ma non nascondiamo che sia costosa in vari termini.