Speech to Text YouTube SubRip Subtitles External Javascript Tutorial

Speech to Text YouTube SubRip Subtitles External Javascript Tutorial

Speech to Text YouTube SubRip Subtitles External Javascript Tutorial

One of “the YouTube SubRip Subtitles peerage” went beyond it’s station yesterday, and we’ve had a little “team talk””, of the ilk of …

… where we’ve been promised it won’t happen again …

For, at least, a week

And so, further to yesterday’s Speech to Text YouTube SubRip Subtitles Tutorial “break out” “the YouTube SubRip Subtitles peerage” has been brought back into line, not even bothering the Video Commentary peerage member in it’s work, via …

… genericizing (and better modularizing) Speech to Text for this work from here on … or at least

a day, maybe

!.


Previous relevant Speech to Text YouTube SubRip Subtitles Tutorial is shown below.

Speech to Text YouTube SubRip Subtitles Tutorial

Speech to Text YouTube SubRip Subtitles Tutorial

Do you remember some way back with Text to Speech macOS Say Large Data Tutorial

So far, it seems, until today, and we were surprised, we’d only been thinking ….

  • Text to Speech macOS say … usage, and expecting success with … Small Amounts of Data … but today, with a future plan in mind we announce …
  • Text to Speech macOS say Large Data Mark I

… an idea we had was the motivation for the recent Text to Speech work? Part of that “set of ideas” was work to do with Speech to Text we only allow functionality interfacing with …

  • non-mobile
  • Google Chrome
  • https: protocol
  • top window

… environments. Today, as a sidestep to the work of yesterday’s Text to Speech macOS Say Large Data Local Web Server Tutorial, but all part of that same set of ideas, we’re not there, but starting down that “integration road” inspired by the great Google Web Speech Demonstration.

Codewise that involved …


Previous relevant Text to Speech macOS Say Large Data Local Web Server Tutorial is shown below.

Text to Speech macOS Say Large Data Local Web Server Tutorial

Text to Speech macOS Say Large Data Local Web Server Tutorial

Are all kludges coming from the “optimistic side of the mind equation“? Today, we did one regarding integrating “say” (which is macOS based only) in our changed macos_say_record.php PHP Voiceover inhouse web application to a local macOS Apache/PHP/MySql web server such as MAMP to see where we are going with all this, when choosing one of the “say” dropdown options, public website “button integration” via Safari web browser …

Where we ran out of options on server and client sides, and just optimistically presented a button in hope, with the understanding we had insufficient proof that clicking on that button would result in navigation to a legitimate local web server URL such as is on a macOS MAMP local web server environment

… and wonder whether this is the case?!

Today’s “work remit” was really simple. On any of the (non argumentative) simplest public website incarnation calls of our Voiceover inhouse web application we wanted to …

  • not present any popup windows (improving on very kludgy efforts of the past) presenting …
  • an evidence based logic offering of a (newly presented) “say” button, the click of which navigates the user to a (so far just macOS local Apache/PHP/MySql web server MAMP port 8888 based) URL able to reach that user’s local operating system “say” command via PHP exec or passthru calls because they’ve got MAMP installed locally along with having macos_say_record.php local system positioning equate to

    HTTP://localhost:8888/macos_say_record.php

Ajax ideas, at document.body onload …

<?php echo ”

var errct=-1, saythere=0;

function lhchk() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.getElementById('saysub').style.backgroundColor='lightblue';
} else {
document.getElementById('saymode').size='3';
}
if (('' + document.URL + '#' + decodeURIComponent(('' + location.hash))).indexOf('media=') != -1) {
var duisb=(" . strlen($knownow) . " > 0 ? '" . $knownow . "' : decodeURIComponent(('' + document.URL + '#' + decodeURIComponent(('' + location.hash))).split('media=')[1].split('&JUNKET&')[0].split('#JUNKET#')[0]).replace(/\ /g,'+'));
if (duisb.indexOf('audio/') != -1) {
//alert(duisb);
//var woa=window.open('', '_blank', 'top=50,left=50,height=400,width=800');
//woa.document.write('<html><body>' + '<br><audio controls><source type=audio/' + duisb.split('audio/')[1].split(';')[0] + ' src=\"' + duisb + '\"></source></audio><br>');
document.getElementById('daudiolater').innerHTML+='<br><audio controls data-preload=none><source type=audio/' + duisb.split('audio/')[1].split(';')[0] + ' src=\"' + duisb + '\" data-onerror=\"playerError();\"></source></audio><br><br><br>';
} else if (duisb.indexOf('video/') != -1) {
document.getElementById('daudiolater').innerHTML+='<br><video controls data-preload=none><source type=video/' + duisb.split('video/')[1].split(';')[0] + ' src=\"' + duisb + '\" data-onerror=\"playerError();\"></source></video><br><br><br>';
} else if (duisb.indexOf('image/') != -1) {
document.getElementById('daudiolater').innerHTML+='<br><img src=\"' + duisb + '\"></img><br>';
} else if (duisb.indexOf('_macoshelp_') != -1) {
document.getElementById('daudiolater').innerHTML+='<br><audio controls data-preload=none><source type=audio/" . $nowknow . " src=\"' + duisb + '\" data-onerror=\"playerError();\"></source></audio><br><br><br>';
}
} else if (('' + document.URL + '#' + decodeURIComponent(('' + location.hash))).indexOf('residue=') != -1) {
document.getElementById('tempidue').value=decodeURIComponent(document.URL.split('tempidue=')[1].split('&')[0].split('#')[0]);
document.getElementById('residue').value=decodeURIComponent(('' + location.hash)).split('residue=')[1].replace(/\ /g,'+');
document.getElementById('trsbut').click();
}

if (document.URL.indexOf('//localhost') == -1 && document.URL.indexOf('?') == -1 && document.URL.indexOf('&') == -1 && document.URL.indexOf('#') == -1) {
if (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if ('notpost' == '" . $notpost . "') {
//opi=window.open('HTTP://localhost:8888/macos_say_record.php?areyou=there', 'theproofif');
zhr = new XMLHttpRequest();
zform=new FormData();
zform.append('areyou', 'there');
zhr.open('get', 'HTTP://localhost:8888/macos_say_record.php', true);
//zhr.setRequestHeader('Access-Control-Allow-Headers', '*');
//zhr.setRequestHeader('Access-Control-Allow-Origin', '*');
//zhr.setRequestHeader('Access-Control-Allow-Methods', 'GET');
zhr.addEventListener('error', errmampshowStuff);
zhr.onreadystatechange = mampshowStuff;
//document.title=' ';
errct=0;
zhr.send(zform);

setTimeout(maybehthree, 5000);
}
}
} else if (document.URL.indexOf('rjmprogramming.com.au/macos_say_record.php') != -1 && document.URL.indexOf('?areyou=there') != -1) {
saythere=saythere; //opi=window.open('//www.rjmprogramming.com.au/macos_say_record.php?there=youare', 'theproofif');
} else if (document.URL.indexOf('//localhost') != -1 && document.URL.indexOf('?') == -1 && document.URL.indexOf('#') == -1) {
saythere=7; //opi=window.open('HTTP://localhost:8888/macos_say_record.php?areyou=there', 'theproofif');
}
}


function errmampshowStuff(evt) {
//document.title+=' ' + zhr.readyState + '|' + zhr.status + '|' + zhr.statusText;
//alert(('response error:', evt.currentTarget.response));
//console.warn(evt);
errct++;
}

function mampshowStuff(evt) {
//document.title+=' ' + zhr.readyState + '/' + zhr.status + '/' + zhr.statusText;
if (zhr.readyState == 4) {
if (zhr.status == 200) {
if (1 == 2) { alert(zhr.responseText); }
}
}
}

“; ?>

… supply the tenuous “evidence based logic” to then try directly calling the macOS MAMP port 8888 based URL into an iframe …


<iframe data-onerror=alert(564); onload=resproof(this); name=theproofif id=theproofif style=display:none; src='/About_Us.html'></iframe>

via


function tosay() {
saythere=6;
location.href='HTTP://localhost:8888/macos_say_record.php';
}

function tosayw() {
saythere=5;
opi=window.open('HTTP://localhost:8888/macos_say_record.php', '_blank');
}

function tosayp() {
saythere=4;
opi=window.open('HTTP://localhost:8888/macos_say_record.php', '_blank', 'top=100,left=' + eval(-800 + screen.width) + ',width=800,height=800');
}

function maybehthree() {
if (errct >= 0 && errct < 3) { console.warn('Errct=' + errct + ' ' + navigator.userAgent); if (navigator.userAgent.indexOf('Safari') != -1) { document.getElementById('myh3').innerHTML+=' ++';
} else {
document.getElementById('myh3').innerHTML+=' ';
}
try {
if (navigator.userAgent.indexOf('Safari') != -1) {
window.open('HTTP://localhost:8888/macos_say_record.php?areyou=there', 'theproofif');
} else {
document.getElementById('theproofif').src='HTTP://localhost:8888/macos_say_record.php?areyou=there';
}
} catch(rteqwe) {
if (1 == 4) { alert('iferr'); }
}

saythere=1;
} else {
console.warn('errct=' + errct + ' ' + navigator.userAgent);
}
}

function resproof(iois) {
if (iois != null) {
console.warn('erRct=' + errct + ' ' + navigator.userAgent);
//alert(1);
var aconto = (iois.contentWindow || iois.contentDocument);
//alert(2);
console.warn('erRCt=' + errct + ' ' + navigator.userAgent);
if (aconto != null) {
//alert(3);
//document.getElementById('myh3').innerHTML+='=';
console.warn('ErRct=' + errct + ' ' + navigator.userAgent);
if (document.getElementById('locbutone') && ('' + iois.src).replace('_proof','_record.php').indexOf('/macos_say_record.php') != -1 && ('' + iois.src).indexOf('//localhost') != -1) {
//document.getElementById('myh3').innerHTML+='+';
console.warn('ErRcT=' + errct + ' ' + navigator.userAgent);
if (document.URL.indexOf('//localhost') == -1 && iois.src.indexOf('//localhost') != -1 && iois.src.indexOf('?areyou=there') != -1) {
//alert('here ' + iois.src);
console.warn('ERRCT = ' + errct + ' ' + navigator.userAgent);
document.getElementById('locbutone').style.display='inline-block';
document.getElementById('locbuttwo').style.display='inline-block';
document.getElementById('locbutthree').style.display='inline-block';
saythere=2;
}
}
if (aconto.document) { aconto = aconto.document; }
//alert(4);
//document.getElementById('myh3').innerHTML+='-';
console.warn('ErRCt=' + errct + ' ' + navigator.userAgent);
if (aconto.body != null) {
//document.getElementById('myh3').innerHTML+='@';
console.warn('ERRct=' + errct + ' ' + navigator.userAgent);
//alert(5);
if (('' + iois.src).replace('_proof','_record.php').indexOf('/macos_say_record.php') != -1 && ('' + iois.src).indexOf('//localhost') != -1) {
//document.getElementById('myh3').innerHTML+='+';
console.warn('ERRCt=' + errct + ' ' + navigator.userAgent);
if (document.getElementById('locbutone') && document.URL.indexOf('//localhost') == -1 && ('' + iois.src).replace('_proof','_record.php').indexOf('/macos_say_record.php') != -1 && iois.src.indexOf('?areyou=there') != -1) {
console.warn('ERRCT=' + errct + ' ' + navigator.userAgent);
//alert('here ' + iois.src);
document.getElementById('locbutone').style.display='inline-block';
document.getElementById('locbuttwo').style.display='inline-block';
document.getElementById('locbutthree').style.display='inline-block';
saythere=3;
}
}
}
}
}
}

… adding this idea onto the progress of yesterday’s Text to Speech macOS Say Large Data Sharing Tutorial.

Satisfying not resorting to kludgy popup window involvement, but only sidestepping CORS issues working with a cross-domain scenario, rather than a scientific and rigorous solution. Sometimes needs must?!


Previous relevant Text to Speech macOS Say Large Data Sharing Tutorial is shown below.

Text to Speech macOS Say Large Data Sharing Tutorial

Text to Speech macOS Say Large Data Sharing Tutorial

Part of improving a web application regarding “large data” is offering some sharing functionality for “large data” scenarios, but this project we have learnt, it being unique regarding the “macOS only say” aspects to it, have taught us not to go overboard trying to cater for everything here. Yesterday’s Text to Speech macOS Say Large Data Tutorial got us started regarding “large data” scenarios where it was just designed for the single user usage. This does not require the transfer of data from that macOS local web browser environment up to a pubic website (Linux) web server environment, involving audio files that can become too large for comfort, often, here.

Our biggest dilemma in this work was, so far in testing we found, only the Firefox web browser would accept either of …

  • “a” “mailto:” link of too big a length involving the audio data URI contained in a hashtag, initiated from localhost MAMP environment
  • call of public website version of macos_say_record.php involving the audio data URI contained in a hashtag, initiated from localhost MAMP environment

… else the all too common …


about:blank#blocked

… would stymie our efforts in “large data” scenarios, where audio data URIs appear within the email link URL hashtag part. Guess we just lost 80% of the audience (except if we tell you now we rely less on audio data URIs appearing within the email link URL hashtag part). But we really wish users would not get spooked by seeing “about:blank#blocked” and think there is anything sinister necessarily, but rather try new web browsers, and try new ways of using free tools. What we are trying to show here, in a free way, is a bit of a way in to some aspects of what people refer to as “artificial intelligence” coming “out of the box” from an operating system. No service fee … just what should be happening from big players down to users on the Internet. It should be applauded, rather than suspected regarding “kludginess”, because the software basis is free, in contrast to the squillions of services popping up that are far from free.

Anyway, you can try downloading our changed macos_say_record.php PHP Voiceover inhouse web application to a local macOS Apache/PHP/MySql web server such as MAMP to see where we are going with all this, when choosing one of the “say” dropdown options, via …


HTTP://localhost:8888/macos_say_record.php

… say?!


Previous relevant Text to Speech macOS Say Large Data Tutorial is shown below.

Text to Speech macOS Say Large Data Tutorial

Text to Speech macOS Say Large Data Tutorial

So far, it seems, until today, and we were surprised, we’d only been thinking ….

  • Text to Speech macOS say … usage, and expecting success with … Small Amounts of Data … but today, with a future plan in mind we announce …
  • Text to Speech macOS say Large Data Mark I

… where you feed the wonderful macOS say command a whole block of code, say?! We did this in all innocence earlier today and … gasp … it failed.

Since then though, we’ve chipped away at some of the issues and discovered two ideas …

  1. for huge amounts of data the macOS say command has a useful …

    -f [inputFileName]

    … switch idea and for …
  2. command lines avoiding the use of ” or ‘ initial delimitation we can use backslash character escaping for those ascii characters less than (32 for) space

There’s more to “large data” issues in this our changed macos_say_record.php PHP Voiceover inhouse web application (that we last talked about with Haiku Image Tutorial) than this start today, but it is an encouraging start for our idea’s progression.

Why do we mention macOS when our public web server is Linux, in terms of operating systems? Yes, this work presupposes you have a macOS operating system in your life, because that is where you see the …


say

… command in its natural environment. Not a pretty sight at times …

Down, I say. “Say”, I down.

… but if you stick to the correct feeding times, well … you may just reap the benefits on a local Apache/PHP/MySql web server environment such as MAMP where we have our macos_say_record.php accessing passthru or exec accessing say via URL …


HTTP://localhost:8888/macos_say_record.php

… where the macOS “out of the box” say command, among other Voiceover ideas, is in play as the great Text to Speech tool that it is.


Previous relevant Haiku Image Tutorial is shown below.

Haiku Image Tutorial

Haiku Image Tutorial

Were you around when Python Cowsay API Cartoon Speech Media Tutorial‘s “genesis tutorial” called Python Cowsay API Primer Tutorial intimated …

… with an integration purpose in mind

? And then, sometime between then and now were you a “Doubting Thomas” thinking we’d forgotten about that statement? And while we’re at it, where were you on February 6, 2025 03:01 AEST?

I’m conflicted if your answers are “No” and “Robbing a bank” but, be that as it may, “we did have an integration purpose in mind” and we’ve come back to it via Haiku poetry, and a web application we wrote some time ago regarding them, and it interfaced to the theme of “the integration purpose in mind” … well you had to be there, said Putricia?!

Yes, it’s the case that hoping for the umpteenth re-researching whether anything manageable Linux wise can match what the great macOS say command has done for Speech to Text relations since Audrey Hepburn’s speech … and coming back with a “No” yet again … we started looking at it a bit more laterally and thought 😜😜 …

But what would the Cow say?

But seriously, no, we just stumbled onto the wonderful cowsay Python API / Command-line tool and wanted to … thinking laterally … have “cowsay” smarts be included into our changed macos_say_record.php PHP Voiceover inhouse web application, itself interfaced to by our changed haiku_animated_gif.html Haiku creating inhouse web application you can also try below …

… so that our changed latest draft can interface in a popup window scenario.


Previous relevant Python Cowsay API Cartoon Speech Media Tutorial is shown below.

Python Cowsay API Cartoon Speech Media Tutorial

Python Cowsay API Cartoon Speech Media Tutorial

As soon as a web application talks about image slides, as we have been dealing with allowing for the creation of cartoons with our recent cowsay Python API / Command-line tool interfacing PHP web application, maybe as Louis Lumière did many years ago, it brings out media thoughts regarding “moving pictures”. We use, here, at our RJM Programming AlmaLinux web server, the great Open Source ffmpeg to help create such media, in today’s case …

  • video
  • animated GIF

… productions using those image slides created via the (again, Open Source) cowsay Python API / Command-line tool …

<?php

if (isset($_GET['getvideo'])) {
$lenv='1';
if (isset($_GET['len'])) {
$lenv=$_GET['len'];
}
if ($_GET['getvideo'] == '1' && $lenv == '0') {
echo "<html><body onload=\" if (parent.document.getElementById('divvideo')) { parent.document.getElementById('divvideo').innerHTML='<video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video>'; } else if (parent.document.getElementById('mysource')) { parent.document.getElementById('mysource').src='data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pvd>Video version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><div id=divvideo><video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video></div>'; } setTimeout(function(){ parent.document.getElementById('pvd').scrollIntoView(); }, 2000); \"></body></html>";
} else {
if (file_exists('/tmp/video' . server_remote_addr() . '.mp4')) {
unlink('/tmp/video' . server_remote_addr() . '.mp4');
}
exec('ffmpeg -framerate 2 -i /tmp/slide_' . server_remote_addr() . '-%03d.png -vcodec libx264 -crf 22 /tmp/video' . server_remote_addr() . '.mp4');
echo "<html><body onload=\" if (parent.document.getElementById('divvideo')) { parent.document.getElementById('divvideo').innerHTML='<video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video>'; } else if (parent.document.getElementById('mysource')) { parent.document.getElementById('mysource').src='data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pvd>Video version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><div id=divvideo><video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video></div>'; } setTimeout(function(){ parent.document.getElementById('pvd').scrollIntoView(); }, 2000); \"></body></html>";
}
exit;
} else if (isset($_GET['getagif'])) {
$lenv='1';
if (isset($_GET['len'])) {
$lenv=$_GET['len'];
}
if ($_GET['getvideo'] == '1' && $lenv == '0') {
echo "<html><body onload=\" if (parent.document.getElementById('mygif')) { parent.document.getElementById('mygif').src='data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pag>Animated GIF version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><img id=mygif src=data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "></img>'; } setTimeout(function(){ parent.document.getElementById('pag').scrollIntoView(); }, 2000); \"></body></html>";
} else {
if (file_exists('/tmp/agif' . server_remote_addr() . '.gif')) {
unlink('/tmp/agif' . server_remote_addr() . '.gif');
}
exec('ffmpeg -framerate 2 -i /tmp/slide_' . server_remote_addr() . '-%03d.png /tmp/agif' . server_remote_addr() . '.gif');
echo "<html><body onload=\" if (parent.document.getElementById('mygif')) { parent.document.getElementById('mygif').src='data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pag>Animated GIF version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><img id=mygif src=data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "></img>'; } setTimeout(function(){ parent.document.getElementById('pag').scrollIntoView(); }, 2000); \"></body></html>";
}
exit;
}

?>

… as a new optional piece of additional functionality offered in our changed “fifth draft” (picking up from Python Cowsay API Cartoon Speech Content Tutorial‘s fourth draft, and further to yesterday’s Text to Image via ImageMagick Primer Tutorial) Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Text to Image via ImageMagick Primer Tutorial is shown below.

Text to Image via ImageMagick Primer Tutorial

Text to Image via ImageMagick Primer Tutorial

Why would a “Primer” tutorial point at a “well along the way” one? Well, a few reasons really …

Yes, the great ImageMagick (and we’re using it’s command line “convert” command here to make this happen) can convert text to images (ie. HTML img elements). Now, we’re not saying you always get perfect matches here, but it is akin to mere mortal dreamers think of as “intelligent scanning”. So, we wanted to have this sidetrack, and we will be resuming “normal transmission” shortly?!

We’ll leave you with some cowsay.php new relevant PHP code to ponder …

<?php

if (isset($_GET['fontlist'])) {
$selpop='';
if (!file_exists('/tmp/imfl.txt')) {
exec('convert -list font > /tmp/imfl.txt');
}
$fcont=file_get_contents('/tmp/imfl.txt');
if (strpos($fcont, 'family: ') !== false) {
$fcs=explode('family: ', $fcont);
for ($iuy=1; $iuy<sizeof($fcs); $iuy++) {
if (strpos($selpop, '>' . explode("\n", $fcs[$iuy])[0] . '<') === false) {
$selpop.="\n selo.innerHTML+='<option value=' + String.fromCharCode(39) + '" . explode("\n", $fcs[$iuy])[0] . "' + String.fromCharCode(39) + '>" . explode("\n", $fcs[$iuy])[0] . "</option>'; \n";
}
}
if ($selpop != '') {
echo "<html><body onload=\" var selos=parent.document.getElementsByTagName('select'); if (eval('' + selos.length) > 0) { var selo=selos[eval(-1 + selos.length)]; " . $selpop . " selo.style.display='inline-block'; selo.style.backgroundColor='#f0f0f0'; } \"></body></html>";
}
}
exit;
} else if (isset($_POST['text'])) {
$perlemoji='';
$emojilabbit="@- "; // vs perl
$iex='png';
$fnt='Courier';
$wdt='800';
$hgt='800';
$psiz='36';
$fcol='black';
$bcol='white';
if (isset($_POST['ext'])) { $iex=str_replace('+',' ',urldecode($_POST['ext'])); }
if (isset($_POST['ffam'])) { $fnt=str_replace('+',' ',urldecode($_POST['ffam'])); }
if (isset($_POST['width'])) { $pwdt=str_replace('+',' ',urldecode($_POST['width'])); }
if (isset($_POST['height'])) { $hgt=str_replace('+',' ',urldecode($_POST['height'])); }
if (isset($_POST['ptsize'])) { $psiz=str_replace('+',' ',urldecode($_POST['ptsize'])); }
if (isset($_POST['fcol'])) { $fcol=str_replace('+',' ',urldecode($_POST['fcol'])); }
if (isset($_POST['bcol'])) { $bcol=str_replace('+',' ',urldecode($_POST['bcol'])); }
$slidename='/tmp/imagerequest_' . server_remote_addr() . '-0.' . $iex;
file_put_contents('/tmp/imagerequest_' . server_remote_addr() . '-0.txt', str_replace('+',' ',urldecode($_POST['text'])));
file_put_contents('/tmp/maybeemojisP.txt', htmlspecialchars(str_replace('+',' ',urldecode($_POST['text'])), ENT_COMPAT,'UTF-8', true));
// yes no &#129684;
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false || strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) { // thanks to https://usage.imagemagick.org/text/#unicode
$outsofar=''; // '\x{201C}Unicode \x{2018}\x{263A}\x{2019} Please\x{201D}'
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_POST['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
} else if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_POST['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
}
$labbit=$emojilabbit;
$perlemoji="perl -e 'binmode(STDOUT, \":utf8\"); print \"" . str_replace("\n", "\x{000A}", $outsofar) . '";' . "' | ";
}
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), "\\") !== false) {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" '; }
file_put_contents('/tmp/imag.cmd', $perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
} else {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt)' . '" '; }
file_put_contents('/tmp/imaG.cmd', $perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename . ' ; chmod 777 ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
}
if (isset($_POST['raw'])) {
header('Content-Type: image/' . $iex);
echo file_get_contents($slidename);
unlink($slidename);
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
exit;
} else {
echo "<html>
<body onload=\"
if (window.parent != window.self) {
var cnvs=parent.document.getElementsByTagName('canvas');
if (eval('' + cnvs.length) > 0) {
var imgsis=new Image();
imgsis.onload=function(event){
var canvasis=cnvs[0];
var cntxis=canvasis.getContext('2d');
cntxis.drawImage(event.target, 0, 0);
};
imgsis.src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else {
var imgs=parent.document.getElementsByTagName('img');
if (eval('' + imgs.length) > 0) {
imgs[0].src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
}
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
\"></body></html>";
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
try {
unlink($slidename);
} catch(Exception $esdw) { }
}
exit;
} else if (isset($_GET['text'])) {
$perlemoji='';
$emojilabbit="@- "; // vs perl
$iex='png';
$fnt='Courier';
$wdt='800';
$hgt='800';
$psiz='36';
$fcol='black';
$bcol='white';
if (isset($_GET['ext'])) { $iex=str_replace('+',' ',urldecode($_GET['ext'])); }
if (isset($_GET['ffam'])) { $fnt=str_replace('+',' ',urldecode($_GET['ffam'])); }
if (isset($_GET['width'])) { $pwdt=str_replace('+',' ',urldecode($_GET['width'])); }
if (isset($_GET['height'])) { $hgt=str_replace('+',' ',urldecode($_GET['height'])); }
if (isset($_GET['ptsize'])) { $psiz=str_replace('+',' ',urldecode($_GET['ptsize'])); }
if (isset($_GET['fcol'])) { $fcol=str_replace('+',' ',urldecode($_GET['fcol'])); }
if (isset($_GET['bcol'])) { $bcol=str_replace('+',' ',urldecode($_GET['bcol'])); }
$slidename='/tmp/imagerequest_' . server_remote_addr() . '-0.' . $iex;
file_put_contents('/tmp/imagerequest_' . server_remote_addr() . '-0.txt', str_replace('+',' ',urldecode($_GET['text'])));
file_put_contents('/tmp/maybeemojisG.txt', htmlspecialchars(str_replace('+',' ',urldecode($_GET['text'])), ENT_COMPAT,'UTF-8', true));
// yes no &#129684;
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false || strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) { // thanks to https://usage.imagemagick.org/text/#unicode
$outsofar=''; // '\x{201C}Unicode \x{2018}\x{263A}\x{2019} Please\x{201D}'
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_GET['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
} else if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_GET['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
}
$labbit=$emojilabbit;
$perlemoji="perl -e 'binmode(STDOUT, \":utf8\"); print \"" . str_replace("\n", "\x{000A}", $outsofar) . '";' . "' | ";
}
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), "\\") !== false) {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" '; }
//file_put_contents('/tmp/imag.cmd', 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" ' . $slidename . ' ; chmod 777 ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
} else {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt)' . '" '; }
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
}
if (isset($_GET['raw'])) {
header('Content-Type: image/' . $iex);
echo file_get_contents($slidename);
unlink($slidename);
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
exit;
} else {
echo "<html>
<body onload=\"
if (window.parent != window.self) {
var cnvs=parent.document.getElementsByTagName('canvas');
if (eval('' + cnvs.length) > 0) {
var imgsis=new Image();
imgsis.onload=function(event){
var canvasis=cnvs[0];
var cntxis=canvasis.getContext('2d');
cntxis.drawImage(event.target, 0, 0);
};
imgsis.src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else {
var imgs=parent.document.getElementsByTagName('img');
if (eval('' + imgs.length) > 0) {
imgs[0].src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
}
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
\"></body></html>";
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
try {
unlink($slidename);
} catch(Exception $esdw) { }
}
exit;
}

?>


Previous relevant Python Cowsay API Cartoon Speech Content Tutorial is shown below.

Python Cowsay API Cartoon Speech Content Tutorial

Python Cowsay API Cartoon Speech Content Tutorial

If you were to ask most people what is more onerous filling in online web forms on the way to making something happen …

  • we’re guessing, rather than saying button presses
  • we’re guessing, they’re more likely to say typing out text …

… with it’s associated tabbing out to negotiate as well. But, supposing we could offer you a “speech to text” approach to performing “typing out text” in our latest cowsay Python API / Command-line tool interfacing PHP web application?

For some years now, we’ve interfaced to a …

  • non-mobile
  • Google Chrome
  • secure URL via https: protocol
  • allowing access to microphone

… means by which we normally access via a “top” hierarchy level call to our inhouse Google Speech to Text API interfacing web application helper.

Isn’t a popup window awkward here? Well, you might think so, but today, we discovered with the Google Chrome browser we used on macOS …

  • we initially call our inhouse Google Speech to Text API interfacing web application helper as a popup sitting in front of the cowsay interfacing parent window …
    <?php echo ”

    function anop() {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    topwo=window_open('https://www.google.com/intl/en/chrome/demos/speech.html','_blank','top=120,left=' + eval(eval('' + screen.width) - 690) + ',width=690,height=550');
    setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000);
    setInterval(function(){ if (!topwo.closed) { topwo.focus(); } topwo.location.href='https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4'; setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000); }, 30000);
    } else {
    topwo=window.open('https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4','_blank','top=120,left=' + eval(eval('' + screen.width) - 690) + ',width=690,height=550');
    setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000);
    setInterval(function(){ if (!topwo.closed) { topwo.focus(); } topwo.location.href='https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4'; setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000); }, 30000);
    }
    }

    “; ?>
  • and found that it was visible until any click or focus back to the cowsay interfacing parent window … normally an annoyance …
  • but not if …
    1. we semi regularly reload the our inhouse Google Speech to Text API interfacing web application helper … to refresh it’s red “recording” button instigation … and then …
    2. even if it remains hidden, it is still apparent to the focussed cowsay interfacing parent window on account of an orange “microphone on recording” icon appearing for the Google Chrome web browser user up at it’s Menu Bar … and …
    3. audio being “sight independent” the user does not have to refocus our inhouse Google Speech to Text API interfacing web application helper, just talk into the microphone just after that new icon appears … so that …
    4. the Google Speech to Text smarts help transfer that resultant text over to the textarea of the cowsay interfacing parent window, even avoiding any need to tab out of that textarea element … ahead of …
    5. the rest of the dropdown selections and button presses needed to achieve the user aim of establishing a new slide, perhaps for a Cartoon being created

… you can see happening with today’s animated GIF presentation on top of the work of yesterday’s Python Cowsay API Cartoon Tutorial in our changed “fourth draft” Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Python Cowsay API Cartoon Tutorial is shown below.

Python Cowsay API Cartoon Tutorial

Python Cowsay API Cartoon Tutorial

We’ve long been interested in online web application ideas that end up with a half decent cartoon the user can create, and share, themselves. “Half decent” becomes “fully decent” with a user who has a great imagination. And so, onto yesterday’s Python Cowsay API Primer Tutorial‘s start with interfacing to the great cowsay Python API / Command-line tool we access via the PHP exec method conduit to our AlmaLinux Apache/PHP/MySql Linux web server, today we’ve extended that …

  • “proof of concept” thinking … onto …
  • cartoon creation “smarts” … starting with (also egged on here by mobile platform problems with monospaced fonts, it seems like)
  • allowing a tabular display of our cowsay components … into …
  • table cells horizontally aligned (and so, less vulnerable to monospacing inaccuracies) … also allowing …
  • within any table cell there is a topmost th table cell wording part above a cowsay character td cell lower part …
  • “half decent” looking via static CSS
    <?php echo ”

    <style>
    margin: 0 0 0 0;
    padding: 0 0 0 0;
    tr { vertical-align: top; }
    td { vertical-align: top; }
    th { vertical-align: top; }

    * { font-family:'Courier New',Courier,monospace; }
    .img-hor { // thanks to https://stackoverflow.com/questions/32875695/flip-mirror-an-image-horizontally-vertically-with-css
    -moz-transform: scaleX(-1);
    -o-transform: scaleX(-1);
    -webkit-transform: scaleX(-1);
    transform: scaleX(-1);
    filter: FlipH;
    -ms-filter: 'FlipH';
    }
    .img-ver { // thanks to https://stackoverflow.com/questions/32875695/flip-mirror-an-image-horizontally-vertically-with-css
    -moz-transform: scaleY(-1);
    -o-transform: scaleY(-1);
    -webkit-transform: scaleY(-1);
    transform: scaleY(-1);
    filter: FlipV;
    -ms-filter: 'FlipV';
    }

    .glow {
    -webkit-animation: glow 1s linear infinite alternate;
    -moz-animation: glow 1s linear infinite alternate;
    animation: glow 1s linear infinite alternate;
    }

    /* Thanks to https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_glowing_text */

    @-webkit-keyframes glow {
    from {
    box-shadow: 0 0 3px #fff, 0 0 5px #fff, 0 0 37px #e60073, 0 0 9px #e60073, 0 0 11px #e60073, 0 0 13px #e60073, 0 0 15px #e60073;
    }

    to {
    box-shadow: 0 0 24px #fff, 0 0 6px #ff4da6, 0 0 8px #ff4da6, 0 0 10px #ff4da6, 0 0 12px #ff4da6, 0 0 14px #ff4da6, 0 0 16px #ff4da6;
    }
    }

    th[id$='0'] {
    background: rgba(224,240,240,0.6); //#e0f0f0;
    }

    th[id$='1'] {
    background: rgba(225,241,241,0.6); //#e1f1f1;
    }

    th[id$='2'] {
    background: rgba(226,242,242,0.6); //#e2f2f2;
    }

    th[id$='3'] {
    background: rgba(227,243,243,0.6); //#e3f3f3;
    }

    th[id$='4'] {
    background: rgba(228,244,244,0.6); //#e4f4f4;
    }

    th[id$='5'] {
    background: rgba(229,245,245,0.6); //#e5f5f5;
    }

    th[id$='6'] {
    background: rgba(230,246,246,0.6); //#e6f6f6;
    }

    th[id$='7'] {
    background: rgba(231,247,247,0.6); //#e7f7f7;
    }

    th[id$='8'] {
    background: rgba(232,248,248,0.6); //#e2f2f2;
    }

    th[id$='9'] {
    background: rgba(233,249,249,0.6); //#e9f9f9;
    }

    td[id$='0'] {
    background: rgba(240,240,240,0.3); //#f0f0f0;
    text-shadow:-1px 1px 1px #ff2d90;
    }

    td[id$='1'] {
    background: rgba(241,241,241,0.3); //#f1f1f1;
    text-shadow:-1px 1px 1px #ff2d91;
    float: bottom;
    }

    td[id$='2'] {
    background: rgba(242,242,242,0.3); //#f2f2f2;
    text-shadow:-1px 1px 1px #ff2d92;
    }

    td[id$='3'] {
    background: rgba(243,243,243,0.3); //#f3f3f3;
    text-shadow:-1px 1px 1px #ff2d93;
    }

    td[id$='4'] {
    background: rgba(244,244,244,0.3); //#f4f4f4;
    text-shadow:-1px 1px 1px #ff2d94;
    }

    td[id$='5'] {
    background: rgba(245,245,245,0.3); //#f5f5f5;
    text-shadow:-1px 1px 1px #ff2d95;
    }

    td[id$='6'] {
    background: rgba(246,246,246,0.3); //#f6f6f6;
    text-shadow:-1px 1px 1px #ff2d96;
    }

    td[id$='7'] {
    background: rgba(247,247,247,0.3); //#f7f7f7;
    text-shadow:-1px 1px 1px #ff2d97;
    }

    td[id$='8'] {
    background: rgba(248,248,248,0.3); //#f8f8f8;
    text-shadow:-1px 1px 1px #ff2d98;
    }

    td[id$='9'] {
    background: rgba(249,249,249,0.3); //#f9f9f9;
    text-shadow:-1px 1px 1px #ff2d99;
    }

    table tbody tr:first-child {
    background: transparent; //#f6f6e6;
    }
    </style>

    “; ?>
    … and then …
  • whenever new cell content happens padding-top adding CSS Javascript DOM nuanced display logic via …
    <?php echo ”

    function paddingtopit() {
    var maxtwo=0, thistwo=0;
    var thhs=[], tdhs=[], it=0;
    var thdids=[];
    //trthtd1
    //trtdtd1
    var tds=document.getElementsByTagName('td');
    for (it=0; it<tds.length; it++) {
    if (('' + tds[it].id).indexOf('trtdtd') != -1) {
    if (('' + tds[it].style.paddingTop).replace(/^null/g,'').replace(/^undefined/g,'').trim() != '') {
    tds[it].style.paddingTop='0px';
    }
    }
    }
    for (it=0; it<tds.length; it++) {
    if (('' + tds[it].id).indexOf('trtdtd') != -1) {
    tdhs.push(eval('' + tds[it].getBoundingClientRect().height));
    thdids.push('' + tds[it].id);
    }
    }
    var ths=document.getElementsByTagName('th');
    for (it=0; it<ths.length; it++) {
    if (('' + ths[it].id).indexOf('trthtd') != -1) {
    thhs.push(eval('' + ths[it].getBoundingClientRect().height));
    thistwo=eval(thhs[it] + tdhs[it]);
    if (thistwo > maxtwo) { maxtwo=thistwo; }
    }
    }
    for (it=0; it<tdhs.length; it++) {
    thistwo=eval(thhs[it] + tdhs[it]);
    if (thistwo < maxtwo) {
    document.getElementById(thdids[it]).style.paddingTop='' + eval(maxtwo - thistwo) + 'px';
    }
    }
    }

    “; ?>
    … so that …
  • cartoons present with “speech bubble” wording aligned to the top in our “cells” (ie. th contenteditable=true editable wording on top of td horizontal flip (double click) and/or vertical flop (right click) editable lower part) with those characters aligned to the bottom

… in our changed “third draft” Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Python Cowsay API Primer Tutorial is shown below.

Python Cowsay API Primer Tutorial

Python Cowsay API Primer Tutorial

We discovered an interesting Open Source Python API / Command-line tool called cowsay which we installed up at our AlmaLinux web server via …


pip install cowsay

… with an integration purpose in mind, so thanks. Before many readers’ time indeed, but some may remember those cute banner printouts that told you who owned the next printout on a spooling “crude graphics” printout in the late 70’s … well cowsay encapsulates those heady days (and who can forget punch cards)?! Before integration, though, we want to test it via a new PHP supervisor on exec method Linux command line interfacings to cowsay.

So we started, with this “first draft” getting places and then this “second draft” with a little more sophistication to leave the day with this interfacer

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in Ajax, eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Speech to Text YouTube SubRip Subtitles Tutorial

Speech to Text YouTube SubRip Subtitles Tutorial

Speech to Text YouTube SubRip Subtitles Tutorial

Do you remember some way back with Text to Speech macOS Say Large Data Tutorial

So far, it seems, until today, and we were surprised, we’d only been thinking ….

  • Text to Speech macOS say … usage, and expecting success with … Small Amounts of Data … but today, with a future plan in mind we announce …
  • Text to Speech macOS say Large Data Mark I

… an idea we had was the motivation for the recent Text to Speech work? Part of that “set of ideas” was work to do with Speech to Text we only allow functionality interfacing with …

  • non-mobile
  • Google Chrome
  • https: protocol
  • top window

… environments. Today, as a sidestep to the work of yesterday’s Text to Speech macOS Say Large Data Local Web Server Tutorial, but all part of that same set of ideas, we’re not there, but starting down that “integration road” inspired by the great Google Web Speech Demonstration.

Codewise that involved …


Previous relevant Text to Speech macOS Say Large Data Local Web Server Tutorial is shown below.

Text to Speech macOS Say Large Data Local Web Server Tutorial

Text to Speech macOS Say Large Data Local Web Server Tutorial

Are all kludges coming from the “optimistic side of the mind equation“? Today, we did one regarding integrating “say” (which is macOS based only) in our changed macos_say_record.php PHP Voiceover inhouse web application to a local macOS Apache/PHP/MySql web server such as MAMP to see where we are going with all this, when choosing one of the “say” dropdown options, public website “button integration” via Safari web browser …

Where we ran out of options on server and client sides, and just optimistically presented a button in hope, with the understanding we had insufficient proof that clicking on that button would result in navigation to a legitimate local web server URL such as is on a macOS MAMP local web server environment

… and wonder whether this is the case?!

Today’s “work remit” was really simple. On any of the (non argumentative) simplest public website incarnation calls of our Voiceover inhouse web application we wanted to …

  • not present any popup windows (improving on very kludgy efforts of the past) presenting …
  • an evidence based logic offering of a (newly presented) “say” button, the click of which navigates the user to a (so far just macOS local Apache/PHP/MySql web server MAMP port 8888 based) URL able to reach that user’s local operating system “say” command via PHP exec or passthru calls because they’ve got MAMP installed locally along with having macos_say_record.php local system positioning equate to

    HTTP://localhost:8888/macos_say_record.php

Ajax ideas, at document.body onload …

<?php echo ”

var errct=-1, saythere=0;

function lhchk() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.getElementById('saysub').style.backgroundColor='lightblue';
} else {
document.getElementById('saymode').size='3';
}
if (('' + document.URL + '#' + decodeURIComponent(('' + location.hash))).indexOf('media=') != -1) {
var duisb=(" . strlen($knownow) . " > 0 ? '" . $knownow . "' : decodeURIComponent(('' + document.URL + '#' + decodeURIComponent(('' + location.hash))).split('media=')[1].split('&JUNKET&')[0].split('#JUNKET#')[0]).replace(/\ /g,'+'));
if (duisb.indexOf('audio/') != -1) {
//alert(duisb);
//var woa=window.open('', '_blank', 'top=50,left=50,height=400,width=800');
//woa.document.write('<html><body>' + '<br><audio controls><source type=audio/' + duisb.split('audio/')[1].split(';')[0] + ' src=\"' + duisb + '\"></source></audio><br>');
document.getElementById('daudiolater').innerHTML+='<br><audio controls data-preload=none><source type=audio/' + duisb.split('audio/')[1].split(';')[0] + ' src=\"' + duisb + '\" data-onerror=\"playerError();\"></source></audio><br><br><br>';
} else if (duisb.indexOf('video/') != -1) {
document.getElementById('daudiolater').innerHTML+='<br><video controls data-preload=none><source type=video/' + duisb.split('video/')[1].split(';')[0] + ' src=\"' + duisb + '\" data-onerror=\"playerError();\"></source></video><br><br><br>';
} else if (duisb.indexOf('image/') != -1) {
document.getElementById('daudiolater').innerHTML+='<br><img src=\"' + duisb + '\"></img><br>';
} else if (duisb.indexOf('_macoshelp_') != -1) {
document.getElementById('daudiolater').innerHTML+='<br><audio controls data-preload=none><source type=audio/" . $nowknow . " src=\"' + duisb + '\" data-onerror=\"playerError();\"></source></audio><br><br><br>';
}
} else if (('' + document.URL + '#' + decodeURIComponent(('' + location.hash))).indexOf('residue=') != -1) {
document.getElementById('tempidue').value=decodeURIComponent(document.URL.split('tempidue=')[1].split('&')[0].split('#')[0]);
document.getElementById('residue').value=decodeURIComponent(('' + location.hash)).split('residue=')[1].replace(/\ /g,'+');
document.getElementById('trsbut').click();
}

if (document.URL.indexOf('//localhost') == -1 && document.URL.indexOf('?') == -1 && document.URL.indexOf('&') == -1 && document.URL.indexOf('#') == -1) {
if (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if ('notpost' == '" . $notpost . "') {
//opi=window.open('HTTP://localhost:8888/macos_say_record.php?areyou=there', 'theproofif');
zhr = new XMLHttpRequest();
zform=new FormData();
zform.append('areyou', 'there');
zhr.open('get', 'HTTP://localhost:8888/macos_say_record.php', true);
//zhr.setRequestHeader('Access-Control-Allow-Headers', '*');
//zhr.setRequestHeader('Access-Control-Allow-Origin', '*');
//zhr.setRequestHeader('Access-Control-Allow-Methods', 'GET');
zhr.addEventListener('error', errmampshowStuff);
zhr.onreadystatechange = mampshowStuff;
//document.title=' ';
errct=0;
zhr.send(zform);

setTimeout(maybehthree, 5000);
}
}
} else if (document.URL.indexOf('rjmprogramming.com.au/macos_say_record.php') != -1 && document.URL.indexOf('?areyou=there') != -1) {
saythere=saythere; //opi=window.open('//www.rjmprogramming.com.au/macos_say_record.php?there=youare', 'theproofif');
} else if (document.URL.indexOf('//localhost') != -1 && document.URL.indexOf('?') == -1 && document.URL.indexOf('#') == -1) {
saythere=7; //opi=window.open('HTTP://localhost:8888/macos_say_record.php?areyou=there', 'theproofif');
}
}


function errmampshowStuff(evt) {
//document.title+=' ' + zhr.readyState + '|' + zhr.status + '|' + zhr.statusText;
//alert(('response error:', evt.currentTarget.response));
//console.warn(evt);
errct++;
}

function mampshowStuff(evt) {
//document.title+=' ' + zhr.readyState + '/' + zhr.status + '/' + zhr.statusText;
if (zhr.readyState == 4) {
if (zhr.status == 200) {
if (1 == 2) { alert(zhr.responseText); }
}
}
}

“; ?>

… supply the tenuous “evidence based logic” to then try directly calling the macOS MAMP port 8888 based URL into an iframe …


<iframe data-onerror=alert(564); onload=resproof(this); name=theproofif id=theproofif style=display:none; src='/About_Us.html'></iframe>

via


function tosay() {
saythere=6;
location.href='HTTP://localhost:8888/macos_say_record.php';
}

function tosayw() {
saythere=5;
opi=window.open('HTTP://localhost:8888/macos_say_record.php', '_blank');
}

function tosayp() {
saythere=4;
opi=window.open('HTTP://localhost:8888/macos_say_record.php', '_blank', 'top=100,left=' + eval(-800 + screen.width) + ',width=800,height=800');
}

function maybehthree() {
if (errct >= 0 && errct < 3) { console.warn('Errct=' + errct + ' ' + navigator.userAgent); if (navigator.userAgent.indexOf('Safari') != -1) { document.getElementById('myh3').innerHTML+=' ++';
} else {
document.getElementById('myh3').innerHTML+=' ';
}
try {
if (navigator.userAgent.indexOf('Safari') != -1) {
window.open('HTTP://localhost:8888/macos_say_record.php?areyou=there', 'theproofif');
} else {
document.getElementById('theproofif').src='HTTP://localhost:8888/macos_say_record.php?areyou=there';
}
} catch(rteqwe) {
if (1 == 4) { alert('iferr'); }
}

saythere=1;
} else {
console.warn('errct=' + errct + ' ' + navigator.userAgent);
}
}

function resproof(iois) {
if (iois != null) {
console.warn('erRct=' + errct + ' ' + navigator.userAgent);
//alert(1);
var aconto = (iois.contentWindow || iois.contentDocument);
//alert(2);
console.warn('erRCt=' + errct + ' ' + navigator.userAgent);
if (aconto != null) {
//alert(3);
//document.getElementById('myh3').innerHTML+='=';
console.warn('ErRct=' + errct + ' ' + navigator.userAgent);
if (document.getElementById('locbutone') && ('' + iois.src).replace('_proof','_record.php').indexOf('/macos_say_record.php') != -1 && ('' + iois.src).indexOf('//localhost') != -1) {
//document.getElementById('myh3').innerHTML+='+';
console.warn('ErRcT=' + errct + ' ' + navigator.userAgent);
if (document.URL.indexOf('//localhost') == -1 && iois.src.indexOf('//localhost') != -1 && iois.src.indexOf('?areyou=there') != -1) {
//alert('here ' + iois.src);
console.warn('ERRCT = ' + errct + ' ' + navigator.userAgent);
document.getElementById('locbutone').style.display='inline-block';
document.getElementById('locbuttwo').style.display='inline-block';
document.getElementById('locbutthree').style.display='inline-block';
saythere=2;
}
}
if (aconto.document) { aconto = aconto.document; }
//alert(4);
//document.getElementById('myh3').innerHTML+='-';
console.warn('ErRCt=' + errct + ' ' + navigator.userAgent);
if (aconto.body != null) {
//document.getElementById('myh3').innerHTML+='@';
console.warn('ERRct=' + errct + ' ' + navigator.userAgent);
//alert(5);
if (('' + iois.src).replace('_proof','_record.php').indexOf('/macos_say_record.php') != -1 && ('' + iois.src).indexOf('//localhost') != -1) {
//document.getElementById('myh3').innerHTML+='+';
console.warn('ERRCt=' + errct + ' ' + navigator.userAgent);
if (document.getElementById('locbutone') && document.URL.indexOf('//localhost') == -1 && ('' + iois.src).replace('_proof','_record.php').indexOf('/macos_say_record.php') != -1 && iois.src.indexOf('?areyou=there') != -1) {
console.warn('ERRCT=' + errct + ' ' + navigator.userAgent);
//alert('here ' + iois.src);
document.getElementById('locbutone').style.display='inline-block';
document.getElementById('locbuttwo').style.display='inline-block';
document.getElementById('locbutthree').style.display='inline-block';
saythere=3;
}
}
}
}
}
}

… adding this idea onto the progress of yesterday’s Text to Speech macOS Say Large Data Sharing Tutorial.

Satisfying not resorting to kludgy popup window involvement, but only sidestepping CORS issues working with a cross-domain scenario, rather than a scientific and rigorous solution. Sometimes needs must?!


Previous relevant Text to Speech macOS Say Large Data Sharing Tutorial is shown below.

Text to Speech macOS Say Large Data Sharing Tutorial

Text to Speech macOS Say Large Data Sharing Tutorial

Part of improving a web application regarding “large data” is offering some sharing functionality for “large data” scenarios, but this project we have learnt, it being unique regarding the “macOS only say” aspects to it, have taught us not to go overboard trying to cater for everything here. Yesterday’s Text to Speech macOS Say Large Data Tutorial got us started regarding “large data” scenarios where it was just designed for the single user usage. This does not require the transfer of data from that macOS local web browser environment up to a pubic website (Linux) web server environment, involving audio files that can become too large for comfort, often, here.

Our biggest dilemma in this work was, so far in testing we found, only the Firefox web browser would accept either of …

  • “a” “mailto:” link of too big a length involving the audio data URI contained in a hashtag, initiated from localhost MAMP environment
  • call of public website version of macos_say_record.php involving the audio data URI contained in a hashtag, initiated from localhost MAMP environment

… else the all too common …


about:blank#blocked

… would stymie our efforts in “large data” scenarios, where audio data URIs appear within the email link URL hashtag part. Guess we just lost 80% of the audience (except if we tell you now we rely less on audio data URIs appearing within the email link URL hashtag part). But we really wish users would not get spooked by seeing “about:blank#blocked” and think there is anything sinister necessarily, but rather try new web browsers, and try new ways of using free tools. What we are trying to show here, in a free way, is a bit of a way in to some aspects of what people refer to as “artificial intelligence” coming “out of the box” from an operating system. No service fee … just what should be happening from big players down to users on the Internet. It should be applauded, rather than suspected regarding “kludginess”, because the software basis is free, in contrast to the squillions of services popping up that are far from free.

Anyway, you can try downloading our changed macos_say_record.php PHP Voiceover inhouse web application to a local macOS Apache/PHP/MySql web server such as MAMP to see where we are going with all this, when choosing one of the “say” dropdown options, via …


HTTP://localhost:8888/macos_say_record.php

… say?!


Previous relevant Text to Speech macOS Say Large Data Tutorial is shown below.

Text to Speech macOS Say Large Data Tutorial

Text to Speech macOS Say Large Data Tutorial

So far, it seems, until today, and we were surprised, we’d only been thinking ….

  • Text to Speech macOS say … usage, and expecting success with … Small Amounts of Data … but today, with a future plan in mind we announce …
  • Text to Speech macOS say Large Data Mark I

… where you feed the wonderful macOS say command a whole block of code, say?! We did this in all innocence earlier today and … gasp … it failed.

Since then though, we’ve chipped away at some of the issues and discovered two ideas …

  1. for huge amounts of data the macOS say command has a useful …

    -f [inputFileName]

    … switch idea and for …
  2. command lines avoiding the use of ” or ‘ initial delimitation we can use backslash character escaping for those ascii characters less than (32 for) space

There’s more to “large data” issues in this our changed macos_say_record.php PHP Voiceover inhouse web application (that we last talked about with Haiku Image Tutorial) than this start today, but it is an encouraging start for our idea’s progression.

Why do we mention macOS when our public web server is Linux, in terms of operating systems? Yes, this work presupposes you have a macOS operating system in your life, because that is where you see the …


say

… command in its natural environment. Not a pretty sight at times …

Down, I say. “Say”, I down.

… but if you stick to the correct feeding times, well … you may just reap the benefits on a local Apache/PHP/MySql web server environment such as MAMP where we have our macos_say_record.php accessing passthru or exec accessing say via URL …


HTTP://localhost:8888/macos_say_record.php

… where the macOS “out of the box” say command, among other Voiceover ideas, is in play as the great Text to Speech tool that it is.


Previous relevant Haiku Image Tutorial is shown below.

Haiku Image Tutorial

Haiku Image Tutorial

Were you around when Python Cowsay API Cartoon Speech Media Tutorial‘s “genesis tutorial” called Python Cowsay API Primer Tutorial intimated …

… with an integration purpose in mind

? And then, sometime between then and now were you a “Doubting Thomas” thinking we’d forgotten about that statement? And while we’re at it, where were you on February 6, 2025 03:01 AEST?

I’m conflicted if your answers are “No” and “Robbing a bank” but, be that as it may, “we did have an integration purpose in mind” and we’ve come back to it via Haiku poetry, and a web application we wrote some time ago regarding them, and it interfaced to the theme of “the integration purpose in mind” … well you had to be there, said Putricia?!

Yes, it’s the case that hoping for the umpteenth re-researching whether anything manageable Linux wise can match what the great macOS say command has done for Speech to Text relations since Audrey Hepburn’s speech … and coming back with a “No” yet again … we started looking at it a bit more laterally and thought 😜😜 …

But what would the Cow say?

But seriously, no, we just stumbled onto the wonderful cowsay Python API / Command-line tool and wanted to … thinking laterally … have “cowsay” smarts be included into our changed macos_say_record.php PHP Voiceover inhouse web application, itself interfaced to by our changed haiku_animated_gif.html Haiku creating inhouse web application you can also try below …

… so that our changed latest draft can interface in a popup window scenario.


Previous relevant Python Cowsay API Cartoon Speech Media Tutorial is shown below.

Python Cowsay API Cartoon Speech Media Tutorial

Python Cowsay API Cartoon Speech Media Tutorial

As soon as a web application talks about image slides, as we have been dealing with allowing for the creation of cartoons with our recent cowsay Python API / Command-line tool interfacing PHP web application, maybe as Louis Lumière did many years ago, it brings out media thoughts regarding “moving pictures”. We use, here, at our RJM Programming AlmaLinux web server, the great Open Source ffmpeg to help create such media, in today’s case …

  • video
  • animated GIF

… productions using those image slides created via the (again, Open Source) cowsay Python API / Command-line tool …

<?php

if (isset($_GET['getvideo'])) {
$lenv='1';
if (isset($_GET['len'])) {
$lenv=$_GET['len'];
}
if ($_GET['getvideo'] == '1' && $lenv == '0') {
echo "<html><body onload=\" if (parent.document.getElementById('divvideo')) { parent.document.getElementById('divvideo').innerHTML='<video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video>'; } else if (parent.document.getElementById('mysource')) { parent.document.getElementById('mysource').src='data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pvd>Video version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><div id=divvideo><video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video></div>'; } setTimeout(function(){ parent.document.getElementById('pvd').scrollIntoView(); }, 2000); \"></body></html>";
} else {
if (file_exists('/tmp/video' . server_remote_addr() . '.mp4')) {
unlink('/tmp/video' . server_remote_addr() . '.mp4');
}
exec('ffmpeg -framerate 2 -i /tmp/slide_' . server_remote_addr() . '-%03d.png -vcodec libx264 -crf 22 /tmp/video' . server_remote_addr() . '.mp4');
echo "<html><body onload=\" if (parent.document.getElementById('divvideo')) { parent.document.getElementById('divvideo').innerHTML='<video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video>'; } else if (parent.document.getElementById('mysource')) { parent.document.getElementById('mysource').src='data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pvd>Video version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><div id=divvideo><video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video></div>'; } setTimeout(function(){ parent.document.getElementById('pvd').scrollIntoView(); }, 2000); \"></body></html>";
}
exit;
} else if (isset($_GET['getagif'])) {
$lenv='1';
if (isset($_GET['len'])) {
$lenv=$_GET['len'];
}
if ($_GET['getvideo'] == '1' && $lenv == '0') {
echo "<html><body onload=\" if (parent.document.getElementById('mygif')) { parent.document.getElementById('mygif').src='data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pag>Animated GIF version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><img id=mygif src=data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "></img>'; } setTimeout(function(){ parent.document.getElementById('pag').scrollIntoView(); }, 2000); \"></body></html>";
} else {
if (file_exists('/tmp/agif' . server_remote_addr() . '.gif')) {
unlink('/tmp/agif' . server_remote_addr() . '.gif');
}
exec('ffmpeg -framerate 2 -i /tmp/slide_' . server_remote_addr() . '-%03d.png /tmp/agif' . server_remote_addr() . '.gif');
echo "<html><body onload=\" if (parent.document.getElementById('mygif')) { parent.document.getElementById('mygif').src='data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pag>Animated GIF version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><img id=mygif src=data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "></img>'; } setTimeout(function(){ parent.document.getElementById('pag').scrollIntoView(); }, 2000); \"></body></html>";
}
exit;
}

?>

… as a new optional piece of additional functionality offered in our changed “fifth draft” (picking up from Python Cowsay API Cartoon Speech Content Tutorial‘s fourth draft, and further to yesterday’s Text to Image via ImageMagick Primer Tutorial) Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Text to Image via ImageMagick Primer Tutorial is shown below.

Text to Image via ImageMagick Primer Tutorial

Text to Image via ImageMagick Primer Tutorial

Why would a “Primer” tutorial point at a “well along the way” one? Well, a few reasons really …

Yes, the great ImageMagick (and we’re using it’s command line “convert” command here to make this happen) can convert text to images (ie. HTML img elements). Now, we’re not saying you always get perfect matches here, but it is akin to mere mortal dreamers think of as “intelligent scanning”. So, we wanted to have this sidetrack, and we will be resuming “normal transmission” shortly?!

We’ll leave you with some cowsay.php new relevant PHP code to ponder …

<?php

if (isset($_GET['fontlist'])) {
$selpop='';
if (!file_exists('/tmp/imfl.txt')) {
exec('convert -list font > /tmp/imfl.txt');
}
$fcont=file_get_contents('/tmp/imfl.txt');
if (strpos($fcont, 'family: ') !== false) {
$fcs=explode('family: ', $fcont);
for ($iuy=1; $iuy<sizeof($fcs); $iuy++) {
if (strpos($selpop, '>' . explode("\n", $fcs[$iuy])[0] . '<') === false) {
$selpop.="\n selo.innerHTML+='<option value=' + String.fromCharCode(39) + '" . explode("\n", $fcs[$iuy])[0] . "' + String.fromCharCode(39) + '>" . explode("\n", $fcs[$iuy])[0] . "</option>'; \n";
}
}
if ($selpop != '') {
echo "<html><body onload=\" var selos=parent.document.getElementsByTagName('select'); if (eval('' + selos.length) > 0) { var selo=selos[eval(-1 + selos.length)]; " . $selpop . " selo.style.display='inline-block'; selo.style.backgroundColor='#f0f0f0'; } \"></body></html>";
}
}
exit;
} else if (isset($_POST['text'])) {
$perlemoji='';
$emojilabbit="@- "; // vs perl
$iex='png';
$fnt='Courier';
$wdt='800';
$hgt='800';
$psiz='36';
$fcol='black';
$bcol='white';
if (isset($_POST['ext'])) { $iex=str_replace('+',' ',urldecode($_POST['ext'])); }
if (isset($_POST['ffam'])) { $fnt=str_replace('+',' ',urldecode($_POST['ffam'])); }
if (isset($_POST['width'])) { $pwdt=str_replace('+',' ',urldecode($_POST['width'])); }
if (isset($_POST['height'])) { $hgt=str_replace('+',' ',urldecode($_POST['height'])); }
if (isset($_POST['ptsize'])) { $psiz=str_replace('+',' ',urldecode($_POST['ptsize'])); }
if (isset($_POST['fcol'])) { $fcol=str_replace('+',' ',urldecode($_POST['fcol'])); }
if (isset($_POST['bcol'])) { $bcol=str_replace('+',' ',urldecode($_POST['bcol'])); }
$slidename='/tmp/imagerequest_' . server_remote_addr() . '-0.' . $iex;
file_put_contents('/tmp/imagerequest_' . server_remote_addr() . '-0.txt', str_replace('+',' ',urldecode($_POST['text'])));
file_put_contents('/tmp/maybeemojisP.txt', htmlspecialchars(str_replace('+',' ',urldecode($_POST['text'])), ENT_COMPAT,'UTF-8', true));
// yes no &#129684;
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false || strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) { // thanks to https://usage.imagemagick.org/text/#unicode
$outsofar=''; // '\x{201C}Unicode \x{2018}\x{263A}\x{2019} Please\x{201D}'
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_POST['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
} else if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_POST['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
}
$labbit=$emojilabbit;
$perlemoji="perl -e 'binmode(STDOUT, \":utf8\"); print \"" . str_replace("\n", "\x{000A}", $outsofar) . '";' . "' | ";
}
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), "\\") !== false) {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" '; }
file_put_contents('/tmp/imag.cmd', $perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
} else {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt)' . '" '; }
file_put_contents('/tmp/imaG.cmd', $perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename . ' ; chmod 777 ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
}
if (isset($_POST['raw'])) {
header('Content-Type: image/' . $iex);
echo file_get_contents($slidename);
unlink($slidename);
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
exit;
} else {
echo "<html>
<body onload=\"
if (window.parent != window.self) {
var cnvs=parent.document.getElementsByTagName('canvas');
if (eval('' + cnvs.length) > 0) {
var imgsis=new Image();
imgsis.onload=function(event){
var canvasis=cnvs[0];
var cntxis=canvasis.getContext('2d');
cntxis.drawImage(event.target, 0, 0);
};
imgsis.src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else {
var imgs=parent.document.getElementsByTagName('img');
if (eval('' + imgs.length) > 0) {
imgs[0].src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
}
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
\"></body></html>";
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
try {
unlink($slidename);
} catch(Exception $esdw) { }
}
exit;
} else if (isset($_GET['text'])) {
$perlemoji='';
$emojilabbit="@- "; // vs perl
$iex='png';
$fnt='Courier';
$wdt='800';
$hgt='800';
$psiz='36';
$fcol='black';
$bcol='white';
if (isset($_GET['ext'])) { $iex=str_replace('+',' ',urldecode($_GET['ext'])); }
if (isset($_GET['ffam'])) { $fnt=str_replace('+',' ',urldecode($_GET['ffam'])); }
if (isset($_GET['width'])) { $pwdt=str_replace('+',' ',urldecode($_GET['width'])); }
if (isset($_GET['height'])) { $hgt=str_replace('+',' ',urldecode($_GET['height'])); }
if (isset($_GET['ptsize'])) { $psiz=str_replace('+',' ',urldecode($_GET['ptsize'])); }
if (isset($_GET['fcol'])) { $fcol=str_replace('+',' ',urldecode($_GET['fcol'])); }
if (isset($_GET['bcol'])) { $bcol=str_replace('+',' ',urldecode($_GET['bcol'])); }
$slidename='/tmp/imagerequest_' . server_remote_addr() . '-0.' . $iex;
file_put_contents('/tmp/imagerequest_' . server_remote_addr() . '-0.txt', str_replace('+',' ',urldecode($_GET['text'])));
file_put_contents('/tmp/maybeemojisG.txt', htmlspecialchars(str_replace('+',' ',urldecode($_GET['text'])), ENT_COMPAT,'UTF-8', true));
// yes no &#129684;
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false || strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) { // thanks to https://usage.imagemagick.org/text/#unicode
$outsofar=''; // '\x{201C}Unicode \x{2018}\x{263A}\x{2019} Please\x{201D}'
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_GET['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
} else if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_GET['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
}
$labbit=$emojilabbit;
$perlemoji="perl -e 'binmode(STDOUT, \":utf8\"); print \"" . str_replace("\n", "\x{000A}", $outsofar) . '";' . "' | ";
}
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), "\\") !== false) {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" '; }
//file_put_contents('/tmp/imag.cmd', 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" ' . $slidename . ' ; chmod 777 ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
} else {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt)' . '" '; }
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
}
if (isset($_GET['raw'])) {
header('Content-Type: image/' . $iex);
echo file_get_contents($slidename);
unlink($slidename);
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
exit;
} else {
echo "<html>
<body onload=\"
if (window.parent != window.self) {
var cnvs=parent.document.getElementsByTagName('canvas');
if (eval('' + cnvs.length) > 0) {
var imgsis=new Image();
imgsis.onload=function(event){
var canvasis=cnvs[0];
var cntxis=canvasis.getContext('2d');
cntxis.drawImage(event.target, 0, 0);
};
imgsis.src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else {
var imgs=parent.document.getElementsByTagName('img');
if (eval('' + imgs.length) > 0) {
imgs[0].src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
}
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
\"></body></html>";
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
try {
unlink($slidename);
} catch(Exception $esdw) { }
}
exit;
}

?>


Previous relevant Python Cowsay API Cartoon Speech Content Tutorial is shown below.

Python Cowsay API Cartoon Speech Content Tutorial

Python Cowsay API Cartoon Speech Content Tutorial

If you were to ask most people what is more onerous filling in online web forms on the way to making something happen …

  • we’re guessing, rather than saying button presses
  • we’re guessing, they’re more likely to say typing out text …

… with it’s associated tabbing out to negotiate as well. But, supposing we could offer you a “speech to text” approach to performing “typing out text” in our latest cowsay Python API / Command-line tool interfacing PHP web application?

For some years now, we’ve interfaced to a …

  • non-mobile
  • Google Chrome
  • secure URL via https: protocol
  • allowing access to microphone

… means by which we normally access via a “top” hierarchy level call to our inhouse Google Speech to Text API interfacing web application helper.

Isn’t a popup window awkward here? Well, you might think so, but today, we discovered with the Google Chrome browser we used on macOS …

  • we initially call our inhouse Google Speech to Text API interfacing web application helper as a popup sitting in front of the cowsay interfacing parent window …
    <?php echo ”

    function anop() {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    topwo=window_open('https://www.google.com/intl/en/chrome/demos/speech.html','_blank','top=120,left=' + eval(eval('' + screen.width) - 690) + ',width=690,height=550');
    setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000);
    setInterval(function(){ if (!topwo.closed) { topwo.focus(); } topwo.location.href='https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4'; setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000); }, 30000);
    } else {
    topwo=window.open('https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4','_blank','top=120,left=' + eval(eval('' + screen.width) - 690) + ',width=690,height=550');
    setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000);
    setInterval(function(){ if (!topwo.closed) { topwo.focus(); } topwo.location.href='https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4'; setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000); }, 30000);
    }
    }

    “; ?>
  • and found that it was visible until any click or focus back to the cowsay interfacing parent window … normally an annoyance …
  • but not if …
    1. we semi regularly reload the our inhouse Google Speech to Text API interfacing web application helper … to refresh it’s red “recording” button instigation … and then …
    2. even if it remains hidden, it is still apparent to the focussed cowsay interfacing parent window on account of an orange “microphone on recording” icon appearing for the Google Chrome web browser user up at it’s Menu Bar … and …
    3. audio being “sight independent” the user does not have to refocus our inhouse Google Speech to Text API interfacing web application helper, just talk into the microphone just after that new icon appears … so that …
    4. the Google Speech to Text smarts help transfer that resultant text over to the textarea of the cowsay interfacing parent window, even avoiding any need to tab out of that textarea element … ahead of …
    5. the rest of the dropdown selections and button presses needed to achieve the user aim of establishing a new slide, perhaps for a Cartoon being created

… you can see happening with today’s animated GIF presentation on top of the work of yesterday’s Python Cowsay API Cartoon Tutorial in our changed “fourth draft” Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Python Cowsay API Cartoon Tutorial is shown below.

Python Cowsay API Cartoon Tutorial

Python Cowsay API Cartoon Tutorial

We’ve long been interested in online web application ideas that end up with a half decent cartoon the user can create, and share, themselves. “Half decent” becomes “fully decent” with a user who has a great imagination. And so, onto yesterday’s Python Cowsay API Primer Tutorial‘s start with interfacing to the great cowsay Python API / Command-line tool we access via the PHP exec method conduit to our AlmaLinux Apache/PHP/MySql Linux web server, today we’ve extended that …

  • “proof of concept” thinking … onto …
  • cartoon creation “smarts” … starting with (also egged on here by mobile platform problems with monospaced fonts, it seems like)
  • allowing a tabular display of our cowsay components … into …
  • table cells horizontally aligned (and so, less vulnerable to monospacing inaccuracies) … also allowing …
  • within any table cell there is a topmost th table cell wording part above a cowsay character td cell lower part …
  • “half decent” looking via static CSS
    <?php echo ”

    <style>
    margin: 0 0 0 0;
    padding: 0 0 0 0;
    tr { vertical-align: top; }
    td { vertical-align: top; }
    th { vertical-align: top; }

    * { font-family:'Courier New',Courier,monospace; }
    .img-hor { // thanks to https://stackoverflow.com/questions/32875695/flip-mirror-an-image-horizontally-vertically-with-css
    -moz-transform: scaleX(-1);
    -o-transform: scaleX(-1);
    -webkit-transform: scaleX(-1);
    transform: scaleX(-1);
    filter: FlipH;
    -ms-filter: 'FlipH';
    }
    .img-ver { // thanks to https://stackoverflow.com/questions/32875695/flip-mirror-an-image-horizontally-vertically-with-css
    -moz-transform: scaleY(-1);
    -o-transform: scaleY(-1);
    -webkit-transform: scaleY(-1);
    transform: scaleY(-1);
    filter: FlipV;
    -ms-filter: 'FlipV';
    }

    .glow {
    -webkit-animation: glow 1s linear infinite alternate;
    -moz-animation: glow 1s linear infinite alternate;
    animation: glow 1s linear infinite alternate;
    }

    /* Thanks to https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_glowing_text */

    @-webkit-keyframes glow {
    from {
    box-shadow: 0 0 3px #fff, 0 0 5px #fff, 0 0 37px #e60073, 0 0 9px #e60073, 0 0 11px #e60073, 0 0 13px #e60073, 0 0 15px #e60073;
    }

    to {
    box-shadow: 0 0 24px #fff, 0 0 6px #ff4da6, 0 0 8px #ff4da6, 0 0 10px #ff4da6, 0 0 12px #ff4da6, 0 0 14px #ff4da6, 0 0 16px #ff4da6;
    }
    }

    th[id$='0'] {
    background: rgba(224,240,240,0.6); //#e0f0f0;
    }

    th[id$='1'] {
    background: rgba(225,241,241,0.6); //#e1f1f1;
    }

    th[id$='2'] {
    background: rgba(226,242,242,0.6); //#e2f2f2;
    }

    th[id$='3'] {
    background: rgba(227,243,243,0.6); //#e3f3f3;
    }

    th[id$='4'] {
    background: rgba(228,244,244,0.6); //#e4f4f4;
    }

    th[id$='5'] {
    background: rgba(229,245,245,0.6); //#e5f5f5;
    }

    th[id$='6'] {
    background: rgba(230,246,246,0.6); //#e6f6f6;
    }

    th[id$='7'] {
    background: rgba(231,247,247,0.6); //#e7f7f7;
    }

    th[id$='8'] {
    background: rgba(232,248,248,0.6); //#e2f2f2;
    }

    th[id$='9'] {
    background: rgba(233,249,249,0.6); //#e9f9f9;
    }

    td[id$='0'] {
    background: rgba(240,240,240,0.3); //#f0f0f0;
    text-shadow:-1px 1px 1px #ff2d90;
    }

    td[id$='1'] {
    background: rgba(241,241,241,0.3); //#f1f1f1;
    text-shadow:-1px 1px 1px #ff2d91;
    float: bottom;
    }

    td[id$='2'] {
    background: rgba(242,242,242,0.3); //#f2f2f2;
    text-shadow:-1px 1px 1px #ff2d92;
    }

    td[id$='3'] {
    background: rgba(243,243,243,0.3); //#f3f3f3;
    text-shadow:-1px 1px 1px #ff2d93;
    }

    td[id$='4'] {
    background: rgba(244,244,244,0.3); //#f4f4f4;
    text-shadow:-1px 1px 1px #ff2d94;
    }

    td[id$='5'] {
    background: rgba(245,245,245,0.3); //#f5f5f5;
    text-shadow:-1px 1px 1px #ff2d95;
    }

    td[id$='6'] {
    background: rgba(246,246,246,0.3); //#f6f6f6;
    text-shadow:-1px 1px 1px #ff2d96;
    }

    td[id$='7'] {
    background: rgba(247,247,247,0.3); //#f7f7f7;
    text-shadow:-1px 1px 1px #ff2d97;
    }

    td[id$='8'] {
    background: rgba(248,248,248,0.3); //#f8f8f8;
    text-shadow:-1px 1px 1px #ff2d98;
    }

    td[id$='9'] {
    background: rgba(249,249,249,0.3); //#f9f9f9;
    text-shadow:-1px 1px 1px #ff2d99;
    }

    table tbody tr:first-child {
    background: transparent; //#f6f6e6;
    }
    </style>

    “; ?>
    … and then …
  • whenever new cell content happens padding-top adding CSS Javascript DOM nuanced display logic via …
    <?php echo ”

    function paddingtopit() {
    var maxtwo=0, thistwo=0;
    var thhs=[], tdhs=[], it=0;
    var thdids=[];
    //trthtd1
    //trtdtd1
    var tds=document.getElementsByTagName('td');
    for (it=0; it<tds.length; it++) {
    if (('' + tds[it].id).indexOf('trtdtd') != -1) {
    if (('' + tds[it].style.paddingTop).replace(/^null/g,'').replace(/^undefined/g,'').trim() != '') {
    tds[it].style.paddingTop='0px';
    }
    }
    }
    for (it=0; it<tds.length; it++) {
    if (('' + tds[it].id).indexOf('trtdtd') != -1) {
    tdhs.push(eval('' + tds[it].getBoundingClientRect().height));
    thdids.push('' + tds[it].id);
    }
    }
    var ths=document.getElementsByTagName('th');
    for (it=0; it<ths.length; it++) {
    if (('' + ths[it].id).indexOf('trthtd') != -1) {
    thhs.push(eval('' + ths[it].getBoundingClientRect().height));
    thistwo=eval(thhs[it] + tdhs[it]);
    if (thistwo > maxtwo) { maxtwo=thistwo; }
    }
    }
    for (it=0; it<tdhs.length; it++) {
    thistwo=eval(thhs[it] + tdhs[it]);
    if (thistwo < maxtwo) {
    document.getElementById(thdids[it]).style.paddingTop='' + eval(maxtwo - thistwo) + 'px';
    }
    }
    }

    “; ?>
    … so that …
  • cartoons present with “speech bubble” wording aligned to the top in our “cells” (ie. th contenteditable=true editable wording on top of td horizontal flip (double click) and/or vertical flop (right click) editable lower part) with those characters aligned to the bottom

… in our changed “third draft” Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Python Cowsay API Primer Tutorial is shown below.

Python Cowsay API Primer Tutorial

Python Cowsay API Primer Tutorial

We discovered an interesting Open Source Python API / Command-line tool called cowsay which we installed up at our AlmaLinux web server via …


pip install cowsay

… with an integration purpose in mind, so thanks. Before many readers’ time indeed, but some may remember those cute banner printouts that told you who owned the next printout on a spooling “crude graphics” printout in the late 70’s … well cowsay encapsulates those heady days (and who can forget punch cards)?! Before integration, though, we want to test it via a new PHP supervisor on exec method Linux command line interfacings to cowsay.

So we started, with this “first draft” getting places and then this “second draft” with a little more sophistication to leave the day with this interfacer

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in Ajax, eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

HTML Element Preload Attribute Browsing Tutorial

HTML Element Preload Attribute Browsing Tutorial

HTML Element Preload Attribute Browsing Tutorial

Two ideas, today, onto yesterday’s HTML Element Preload Attribute Primer Tutorial

  1. on iPhone types of mobile the preload=”none” video used to be reduced to nothing, and this situation was improved via

    <table id=mytable style="width:100%;">
    <tr><th style="overflow-y:hidden;" colspan=3>Media <select id=mysel onchange=process(this);><option value=video>Video</option><option value=audio>Audio</option><option value=image>Image</option></select> Preload Attribute Effects <iframe class="spag" scrolling="no" onload="limitb(this);" id="cbi" frameborder="0" style="overflow-y:hidden;width:173px;height:218px;margin-top:-204px;" data-accept="video/*audio/*" src="/HTMLCSS/client_browsing.htm"></iframe></th></tr>
    <tr><th>none</th><th>metadata</th><th>auto</th></tr>
    <tr><td style="width:33%;background-color:rgba(255,0,0,0.1);" id=preloadnone>
    <video style="width:100%;" preload="none" controls><source src='//www.rjmprogramming.com.au/bluetooth_movie.mp4' type='video/mp4'></source></video>
    </td><td style="width:33%;background-color:rgba(255,255,0,0.1);" id=preloadmetadata>
    <video style="width:100%;" preload="metadata" controls><source src='//www.rjmprogramming.com.au/bluetooth_movie.mp4' type='video/mp4'></source></video>
    </td><td style="width:33%;background-color:rgba(0,255,0,0.1);" id=preloadauto>
    <video style="width:100%;" preload="auto" controls><source src='//www.rjmprogramming.com.au/bluetooth_movie.mp4' type='video/mp4'></source></video>
    </td></tr>
    </table>

    … and then there was the matter of …
  2. content choices were pretty static but we thought that could be bettered by offering the user the chance to browse for local media files themselves …

    function lookforresult() {
    if (document.getElementById('result').innerHTML.indexOf('data:') == 0) {
    durl=document.getElementById('result').innerHTML;
    document.getElementById('result').innerHTML='';
    if (durl.indexOf('data:image/') == 0) {
    document.getElementById('cto').value=durl;
    document.getElementById('myif').src='./media_preload.html?called=' + Math.floor(Math.random() * 19897865);
    document.getElementById('myif').style.display='block';
    } else if (durl.indexOf('data:video/') == 0) {
    templates[0]=templates[1].replace(templates[0].split(" src='")[1].split("'")[0], durl);
    document.getElementById('mysel').value='video';
    process(document.getElementById('mysel'));
    } else if (durl.indexOf('data:audio/') == 0) {
    templates[1]=templates[1].replace(templates[1].split(" src='")[1].split("'")[0], durl);
    document.getElementById('mysel').value='audio';
    process(document.getElementById('mysel'));
    }
    }
    }

    setInterval(lookforresult, 5000);

in a second draft media_preload.html idea for you today.


Previous relevant HTML Element Preload Attribute Primer Tutorial is shown below.

HTML Element Preload Attribute Primer Tutorial

HTML Element Preload Attribute Primer Tutorial

We have a very simple media …

  • video
  • audio
  • image

“proof of concept” idea for you today, touching on ideas with web browser web applications concerning the preloading, or not, for media files.

With video and audio elements, this can involve the use of the HTML element attribute …


preload

… while for images, they can be helped with preloading via an HTML link element such as …


<link rel="preload" href="/inhouse_slideshow_css.jpeg" as="image" type="image/jpeg" />

… within the head element.

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in eLearning, Event-Driven Programming, Operating System, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , | Leave a comment

HTML Element Preload Attribute Primer Tutorial

HTML Element Preload Attribute Primer Tutorial

HTML Element Preload Attribute Primer Tutorial

We have a very simple media …

  • video
  • audio
  • image

“proof of concept” idea for you today, touching on ideas with web browser web applications concerning the preloading, or not, for media files.

With video and audio elements, this can involve the use of the HTML element attribute …


preload

… while for images, they can be helped with preloading via an HTML link element such as …


<link rel="preload" href="/inhouse_slideshow_css.jpeg" as="image" type="image/jpeg" />

… within the head element.

If this was interesting you may be interested in this too.

Posted in eLearning, Tutorials | Tagged , , , , , , , , , , , , | Leave a comment

PhotoBooth Video Snippet via Ffmpeg Command Line Tutorial

PhotoBooth Video Snippet via Ffmpeg Command Line Tutorial

PhotoBooth Video Snippet via Ffmpeg Command Line Tutorial

Regarding the “making of” the recent Bluetooth Spotify Auto Stop Start Primer Tutorial many people will be unsurprised that the video was created via macOS “out of the box” …


PhotoBooth

… desktop application in “video mode”. Often in this mode of video creation there is this awkward bit at the end of the video recording where the user leans over to click the Stop button on the PhotoBooth application, and often records themselves doing this.

For a semi-technical video explaining an observation or procedure in Information Technology, that part at the end is a bit offputting, to our mind.

So, in a scenario like this, we usually turn to the great, and free, ffmpeg command line (including macOS) tool, also talked about with Concatenating Video on Command Line Tutorial. But we could not remember trimming a video this way before, and turned to this great link, thanks to arrive at …


ffmpeg -ss 00:00:00 -to 00:01:54 -i bluetooth_movie.mov bluetooth_movie.mp4

… to make this happen (for one minute fifty four seconds, that is)


Previous relevant Concatenating Video on Command Line Tutorial is shown below.

Concatenating Video on Command Line Tutorial

Concatenating Video on Command Line Tutorial

You might also want to think of today’s tutorial as a (follow up to) “Making Of” presentation with reference to yesterday’s Camera App Photo Live Mode Sharing Tutorial where we used the wonderful command line ffmpeg tool. For us, this “command line” was macOS 10.14.5 Mojave one, but ffmpeg stresses its cross-platform capabilities. The videos relating to …

  • yesterday’s MP4 explanatory video was created via …
    1. macOS MacBook Pro PhotoBooth …
    2. Video mode
    3. two finger gesture Export…

  • and the day before’s MP4 explanatory video was created via …
    1. iOS iPad Camera app (filming iPhone creating its Camera app Live mode photos) …
    2. Video mode

  • share to macOS MacBook Pro (and we refer you to yesterday’s Camera App Photo Live Mode Sharing Tutorial)
  • at (macOS (Terminal application)) command line … convert MOV to MP4 via …

    ffmpeg -i avideofile.mov avideofile.mp4

… and as you would appreciate if you are into creating graphic media presentation content, it is challenging to make the one apt “take” of a video. Sometimes, even, you get a part of a procedure “semi-right” and rather than completely start over with another video, “life intervenes” to mean that second video just takes up where the first left off. Yesterday’s explanatory video was of this ilk, and we “let it slide” that way for a day. Today, though, we take up the challenge …

But why don’t we try to concatenate two videos into one to give a bigger picture of the explanatory video result?

… and the answer to this was staring us in the face (and isn’t it just mortifying saying “Good morning, ffmpeg”), with command line “ffmpeg” being capable of this, and we recommend you read this useful link, thanks, regarding further reading here, because we had some false starts, but ending up realizing that the “ts” (Transport Stream) format video as a middleperson made both doing and understanding “ffmpeg” video concatenations easy. So …

  1. to “ffmpeg” video concatenate …
  2. primary to intermediate video format conversion …
    Broadly …
    Convert primary “MOV” media formats to intermediate “ts” videos
    Specifically, on macOS Terminal, for two roughly minute long videos, that second command below related to yesterday’s explanatory video …

    ffmpeg -i air_drop_messages_live_0photo.mov air_drop_messages_live_0photo.ts
    ffmpeg -i air_drop_messages_live_photo.mov air_drop_messages_live_photo.ts
  3. concatenate videos in intermediate format …
    Broadly …
    Concatenate “ts” videos into another “ts” video
    Specifically, on macOS Terminal …

    ffmpeg -i "concat:air_drop_messages_live_0photo.ts|air_drop_messages_live_photo.ts" -c copy air_drop_messages_live_photo_more.ts
  4. intermediate to output video format conversion …
    Broadly …
    Convert intermediate “ts” concatenated video into output “MP4” (concatenated) video
    Specifically, on macOS Terminal …

    ffmpeg -i air_drop_messages_live_photo_more.ts air_drop_messages_live_photo_more.mp4

… as you can see with the resultant concatenated video (about two minutes) below …

… some AirDrop and AirPlay iPhone Settings demonstrations (in the first take not used yesterday, but prepended today) adds to the Sharing explanatory video for the “Sharing of iOS Camera app Live mode Photos”. This explanatory video “concatenated take” was created via …

  • macOS MacBook Pro PhotoBooth Video mode … filming …
  • iPhone (sharer) and iPad (sharee?) mounted on a music stand … then …
  • two finger gesture Export… (exports to MOV video, for us)

Did you know?

Knowing very little about the ffmpeg intermediate “ts” (Transport Stream) video format we looked it up and discovered it is a streaming video format. So what, you might ask? Well, some time back, YouTube was recommending use of streaming video formats in preference to other video formats, and so we decided to upload to YouTube ffmpeg’s “ts” version of this video for your interest and perusal, perhaps …


Previous relevant Camera App Photo Live Mode Sharing Tutorial is shown below.

Camera App Photo Live Mode Primer Tutorial

Camera App Photo Live Mode Sharing Tutorial

Yesterday’s Camera App Photo Live Mode Primer Tutorial talked about the iOS Camera app’s Live mode functionality, creating an animated GIF type of photo that can be stored in the …


Albums -> Media Types -> Live Photos

… area. Sharing via the Mail option of the Photos app’s Sharing icon and menu lost the “animation” (for the emailee), creating a “still” (photo) as the downloaded media. But, as promised in the Stop Press yesterday, there are some sharing options that can keep that “animated” (GIF) feel …

  • via Messages app the shared photo will play like an animated GIF on a long touch (perhaps also on non-iOS devices (we did not test this?))
  • for sharing with other iOS devices within range and operating system viability you can use AirDrop

… as you can see demonstrated below …

Did you know?

In amongst the Apple “stable” this animated GIF “look and feel” is exclusively a (mobile) iOS (ie. iPhone, iPad etcetera) thing. The same SMS viewed on this macOS MacBook Pro displays as a “still” (photo), and the macOS involvement makes it a “still” even forwarding this on to iOS via the macOS Messages app.


Previous relevant Camera App Photo Live Mode Primer Tutorial is shown below.

Camera App Photo Live Mode Primer Tutorial

Camera App Photo Live Mode Primer Tutorial

Meanwhile, back at Apple‘s iPhone Camera App, further to Camera App Video Slow Motion Primer Tutorial, we wanted to find out more about that yellow “dart board” type “button” up the top that can be toggled between …

  • live off
  • live

What is “Live Mode” as far as the iOS Camera app goes? We consulted Google and came to How to Use Live Photos on iPhone and iPad

Basically, a Live Photo is a combination of a video clip and a still image that results in something akin to an animated GIF when long pressed. With the feature enabled, your iPhone or iPad grabs up to 1.5 seconds of video before and up to 1.5 seconds of video after you tap the shutter button.

… as a “very cute” hybrid between “photo” mode and “video” mode and “slo-mo” (video) mode. Afterwards, if your “live” mode photo is saved into Photos it will sit in …


Albums -> Media Types -> Live Photos

… and will present, initially, like a “still”, but touch (for a goodly time), will “very cutely” turn into an animation (like an animated GIF that you control).

So what happens if you share this “live photo” via email? On this MacBook Pro, it gets shared as a “still”. On an iPad (opened email) it shares as a “still”, as it does on the same iPhone device it was taken on, in that iPhone’s Mail app. But …


Touch Photos app icon -> Albums -> Media Types -> Live Photos -> Long Touch on "Live Photo" of interest

… brings the whole “back story” to light.

Stop Press

If you want to share a Live Mode iPhone Camera app photo in an SMS via Messages app or with another Apple iOS device in the same building, the sharing news is better. We’ll demonstrate tomorrow.


Previous relevant Camera App Video Slow Motion Primer Tutorial is shown below.

Camera App Video Slow Motion Primer Tutorial

Camera App Video Slow Motion Primer Tutorial

Continuing the video theme of yesterday’s QuickTime Player Mov Video Conversion Tutorial today we try out the iPhone (ie. iOS) Camera app’s Video mode’s Slo-Mo mode of use.

Get ready for longer but attention grabbing videos straight from the source

No doubt many of you out there have been trying this feature out yourselves?!


Previous relevant QuickTime Player Mov Video Conversion Tutorial is shown below.

QuickTime Player Mov Video Conversion Tutorial

QuickTime Player Mov Video Conversion Tutorial

Yesterday’s Spinning Around Primer Tutorial changed quite a bit between 27th March 2019 06:00 and 11:20 AEST. Why? Well, our iPhone6 saves its videos (from the Camera iOS application) in *.mov format. This *.mov has an associated mimetype video/quicktime and as you may surmise from that mimetype it’s success as a video playing format depends quite a bit on the user having access to the QuickTime Player application. We say quite a bit here because you can sometimes open an *.mov based URL in a web browser of a computer without QuickTime Player installed, and believe I’ve seen the video be played that way, but with yesterday’s tutorial, we were asking the *.mov be played within an HTML video element (albeit one with no cross-domain issues). The problem here even for computers with QuickTime Player installed …

  • you see a blank black video screen (with controls (because we specified that with our …

    <video style='width:100%;' controlshttp://www.rjmprogramming.com.au/wordpress/wp-admin/post.php?post=44345&action=editsource type='video/quicktime' src='http://www.rjmprogramming.com.au/Mac/iPhone/spinning_around.mov'http://www.rjmprogramming.com.au/wordpress/wp-admin/post.php?post=44345&action=edit/source></video>

    … video element HTML above)
  • you click the play button and nothing happens

All a bit disappointing, but please read on.

Then we set out thinking about conversion from …

  • *.mov to *.m4v via older QuickTime Player Version 10.4 (894.12) (no longer available as of Version 10.5 (928.50)) … which we associated with its video element in Spinning Around Primer Tutorial
  • *.mov to *.mp4 via ffmpeg and help from this great link, thanks, to use on a MacBook Pro (Terminal application) command line, the command …

    ffmpeg -i spinning_around.mov -vcodec h264 -acodec mp2 spinning_around.mp4

    … which we associated with clicking on the tutorial picture of yesterday’s Spinning Around Primer Tutorial

… and then reflecting, and thinking this cannot be so, we got to another great link, thanks, and realized that …


<video style='width:100%;' controls><source type='video/mp4' src='http://www.rjmprogramming.com.au/Mac/iPhone/spinning_around.mov'></source></video>

… could be played in the video element, as below …

You can also see this play out at WordPress 4.1.1’s QuickTime Player Mov Video Conversion Tutorial.


Previous relevant Spinning Around Primer Tutorial is shown below.

Spinning Around Primer Tutorial

Spinning Around Primer Tutorial

That Kylie Minogue song “I’m spinning around …” spinssprings to mind with today’s tutorial.

Have you ever wanted to made a video to try to make yourself, or someone else, dizzy? Well, we thought about this, and decided we’d …

  1. use an iPhone …
  2. start up its Camera app
  3. get it ready for (normal) Video mode
  4. grab a broom
  5. grab a rubber band, the thicker the safer for your iPhone … please be careful …
  6. bind the iPhone onto the broom handle via the rubber band, as tightly as you can
  7. tap the red button awaiting you starting the Video recording, on the iPhone … doh! …
  8. spin the broom handle for a while … we did about 10 seconds
  9. tap the red button to stop recording
  10. share the dizzifying Video, as we do here and below

Are you dizzy yet?

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in eLearning, Operating System, Software, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Text to Speech macOS Say Large Data Local Web Server Tutorial

Text to Speech macOS Say Large Data Local Web Server Tutorial

Text to Speech macOS Say Large Data Local Web Server Tutorial

Are all kludges coming from the “optimistic side of the mind equation“? Today, we did one regarding integrating “say” (which is macOS based only) in our changed macos_say_record.php PHP Voiceover inhouse web application to a local macOS Apache/PHP/MySql web server such as MAMP to see where we are going with all this, when choosing one of the “say” dropdown options, public website “button integration” via Safari web browser …

Where we ran out of options on server and client sides, and just optimistically presented a button in hope, with the understanding we had insufficient proof that clicking on that button would result in navigation to a legitimate local web server URL such as is on a macOS MAMP local web server environment

… and wonder whether this is the case?!

Today’s “work remit” was really simple. On any of the (non argumentative) simplest public website incarnation calls of our Voiceover inhouse web application we wanted to …

  • not present any popup windows (improving on very kludgy efforts of the past) presenting …
  • an evidence based logic offering of a (newly presented) “say” button, the click of which navigates the user to a (so far just macOS local Apache/PHP/MySql web server MAMP port 8888 based) URL able to reach that user’s local operating system “say” command via PHP exec or passthru calls because they’ve got MAMP installed locally along with having macos_say_record.php local system positioning equate to

    HTTP://localhost:8888/macos_say_record.php

Ajax ideas, at document.body onload …

<?php echo ”

var errct=-1, saythere=0;

function lhchk() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.getElementById('saysub').style.backgroundColor='lightblue';
} else {
document.getElementById('saymode').size='3';
}
if (('' + document.URL + '#' + decodeURIComponent(('' + location.hash))).indexOf('media=') != -1) {
var duisb=(" . strlen($knownow) . " > 0 ? '" . $knownow . "' : decodeURIComponent(('' + document.URL + '#' + decodeURIComponent(('' + location.hash))).split('media=')[1].split('&JUNKET&')[0].split('#JUNKET#')[0]).replace(/\ /g,'+'));
if (duisb.indexOf('audio/') != -1) {
//alert(duisb);
//var woa=window.open('', '_blank', 'top=50,left=50,height=400,width=800');
//woa.document.write('<html><body>' + '<br><audio controls><source type=audio/' + duisb.split('audio/')[1].split(';')[0] + ' src=\"' + duisb + '\"></source></audio><br>');
document.getElementById('daudiolater').innerHTML+='<br><audio controls data-preload=none><source type=audio/' + duisb.split('audio/')[1].split(';')[0] + ' src=\"' + duisb + '\" data-onerror=\"playerError();\"></source></audio><br><br><br>';
} else if (duisb.indexOf('video/') != -1) {
document.getElementById('daudiolater').innerHTML+='<br><video controls data-preload=none><source type=video/' + duisb.split('video/')[1].split(';')[0] + ' src=\"' + duisb + '\" data-onerror=\"playerError();\"></source></video><br><br><br>';
} else if (duisb.indexOf('image/') != -1) {
document.getElementById('daudiolater').innerHTML+='<br><img src=\"' + duisb + '\"></img><br>';
} else if (duisb.indexOf('_macoshelp_') != -1) {
document.getElementById('daudiolater').innerHTML+='<br><audio controls data-preload=none><source type=audio/" . $nowknow . " src=\"' + duisb + '\" data-onerror=\"playerError();\"></source></audio><br><br><br>';
}
} else if (('' + document.URL + '#' + decodeURIComponent(('' + location.hash))).indexOf('residue=') != -1) {
document.getElementById('tempidue').value=decodeURIComponent(document.URL.split('tempidue=')[1].split('&')[0].split('#')[0]);
document.getElementById('residue').value=decodeURIComponent(('' + location.hash)).split('residue=')[1].replace(/\ /g,'+');
document.getElementById('trsbut').click();
}

if (document.URL.indexOf('//localhost') == -1 && document.URL.indexOf('?') == -1 && document.URL.indexOf('&') == -1 && document.URL.indexOf('#') == -1) {
if (!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if ('notpost' == '" . $notpost . "') {
//opi=window.open('HTTP://localhost:8888/macos_say_record.php?areyou=there', 'theproofif');
zhr = new XMLHttpRequest();
zform=new FormData();
zform.append('areyou', 'there');
zhr.open('get', 'HTTP://localhost:8888/macos_say_record.php', true);
//zhr.setRequestHeader('Access-Control-Allow-Headers', '*');
//zhr.setRequestHeader('Access-Control-Allow-Origin', '*');
//zhr.setRequestHeader('Access-Control-Allow-Methods', 'GET');
zhr.addEventListener('error', errmampshowStuff);
zhr.onreadystatechange = mampshowStuff;
//document.title=' ';
errct=0;
zhr.send(zform);

setTimeout(maybehthree, 5000);
}
}
} else if (document.URL.indexOf('rjmprogramming.com.au/macos_say_record.php') != -1 && document.URL.indexOf('?areyou=there') != -1) {
saythere=saythere; //opi=window.open('//www.rjmprogramming.com.au/macos_say_record.php?there=youare', 'theproofif');
} else if (document.URL.indexOf('//localhost') != -1 && document.URL.indexOf('?') == -1 && document.URL.indexOf('#') == -1) {
saythere=7; //opi=window.open('HTTP://localhost:8888/macos_say_record.php?areyou=there', 'theproofif');
}
}


function errmampshowStuff(evt) {
//document.title+=' ' + zhr.readyState + '|' + zhr.status + '|' + zhr.statusText;
//alert(('response error:', evt.currentTarget.response));
//console.warn(evt);
errct++;
}

function mampshowStuff(evt) {
//document.title+=' ' + zhr.readyState + '/' + zhr.status + '/' + zhr.statusText;
if (zhr.readyState == 4) {
if (zhr.status == 200) {
if (1 == 2) { alert(zhr.responseText); }
}
}
}

“; ?>

… supply the tenuous “evidence based logic” to then try directly calling the macOS MAMP port 8888 based URL into an iframe …


<iframe data-onerror=alert(564); onload=resproof(this); name=theproofif id=theproofif style=display:none; src='/About_Us.html'></iframe>

via


function tosay() {
saythere=6;
location.href='HTTP://localhost:8888/macos_say_record.php';
}

function tosayw() {
saythere=5;
opi=window.open('HTTP://localhost:8888/macos_say_record.php', '_blank');
}

function tosayp() {
saythere=4;
opi=window.open('HTTP://localhost:8888/macos_say_record.php', '_blank', 'top=100,left=' + eval(-800 + screen.width) + ',width=800,height=800');
}

function maybehthree() {
if (errct >= 0 && errct < 3) { console.warn('Errct=' + errct + ' ' + navigator.userAgent); if (navigator.userAgent.indexOf('Safari') != -1) { document.getElementById('myh3').innerHTML+=' ++';
} else {
document.getElementById('myh3').innerHTML+=' ';
}
try {
if (navigator.userAgent.indexOf('Safari') != -1) {
window.open('HTTP://localhost:8888/macos_say_record.php?areyou=there', 'theproofif');
} else {
document.getElementById('theproofif').src='HTTP://localhost:8888/macos_say_record.php?areyou=there';
}
} catch(rteqwe) {
if (1 == 4) { alert('iferr'); }
}

saythere=1;
} else {
console.warn('errct=' + errct + ' ' + navigator.userAgent);
}
}

function resproof(iois) {
if (iois != null) {
console.warn('erRct=' + errct + ' ' + navigator.userAgent);
//alert(1);
var aconto = (iois.contentWindow || iois.contentDocument);
//alert(2);
console.warn('erRCt=' + errct + ' ' + navigator.userAgent);
if (aconto != null) {
//alert(3);
//document.getElementById('myh3').innerHTML+='=';
console.warn('ErRct=' + errct + ' ' + navigator.userAgent);
if (document.getElementById('locbutone') && ('' + iois.src).replace('_proof','_record.php').indexOf('/macos_say_record.php') != -1 && ('' + iois.src).indexOf('//localhost') != -1) {
//document.getElementById('myh3').innerHTML+='+';
console.warn('ErRcT=' + errct + ' ' + navigator.userAgent);
if (document.URL.indexOf('//localhost') == -1 && iois.src.indexOf('//localhost') != -1 && iois.src.indexOf('?areyou=there') != -1) {
//alert('here ' + iois.src);
console.warn('ERRCT = ' + errct + ' ' + navigator.userAgent);
document.getElementById('locbutone').style.display='inline-block';
document.getElementById('locbuttwo').style.display='inline-block';
document.getElementById('locbutthree').style.display='inline-block';
saythere=2;
}
}
if (aconto.document) { aconto = aconto.document; }
//alert(4);
//document.getElementById('myh3').innerHTML+='-';
console.warn('ErRCt=' + errct + ' ' + navigator.userAgent);
if (aconto.body != null) {
//document.getElementById('myh3').innerHTML+='@';
console.warn('ERRct=' + errct + ' ' + navigator.userAgent);
//alert(5);
if (('' + iois.src).replace('_proof','_record.php').indexOf('/macos_say_record.php') != -1 && ('' + iois.src).indexOf('//localhost') != -1) {
//document.getElementById('myh3').innerHTML+='+';
console.warn('ERRCt=' + errct + ' ' + navigator.userAgent);
if (document.getElementById('locbutone') && document.URL.indexOf('//localhost') == -1 && ('' + iois.src).replace('_proof','_record.php').indexOf('/macos_say_record.php') != -1 && iois.src.indexOf('?areyou=there') != -1) {
console.warn('ERRCT=' + errct + ' ' + navigator.userAgent);
//alert('here ' + iois.src);
document.getElementById('locbutone').style.display='inline-block';
document.getElementById('locbuttwo').style.display='inline-block';
document.getElementById('locbutthree').style.display='inline-block';
saythere=3;
}
}
}
}
}
}

… adding this idea onto the progress of yesterday’s Text to Speech macOS Say Large Data Sharing Tutorial.

Satisfying not resorting to kludgy popup window involvement, but only sidestepping CORS issues working with a cross-domain scenario, rather than a scientific and rigorous solution. Sometimes needs must?!


Previous relevant Text to Speech macOS Say Large Data Sharing Tutorial is shown below.

Text to Speech macOS Say Large Data Sharing Tutorial

Text to Speech macOS Say Large Data Sharing Tutorial

Part of improving a web application regarding “large data” is offering some sharing functionality for “large data” scenarios, but this project we have learnt, it being unique regarding the “macOS only say” aspects to it, have taught us not to go overboard trying to cater for everything here. Yesterday’s Text to Speech macOS Say Large Data Tutorial got us started regarding “large data” scenarios where it was just designed for the single user usage. This does not require the transfer of data from that macOS local web browser environment up to a pubic website (Linux) web server environment, involving audio files that can become too large for comfort, often, here.

Our biggest dilemma in this work was, so far in testing we found, only the Firefox web browser would accept either of …

  • “a” “mailto:” link of too big a length involving the audio data URI contained in a hashtag, initiated from localhost MAMP environment
  • call of public website version of macos_say_record.php involving the audio data URI contained in a hashtag, initiated from localhost MAMP environment

… else the all too common …


about:blank#blocked

… would stymie our efforts in “large data” scenarios, where audio data URIs appear within the email link URL hashtag part. Guess we just lost 80% of the audience (except if we tell you now we rely less on audio data URIs appearing within the email link URL hashtag part). But we really wish users would not get spooked by seeing “about:blank#blocked” and think there is anything sinister necessarily, but rather try new web browsers, and try new ways of using free tools. What we are trying to show here, in a free way, is a bit of a way in to some aspects of what people refer to as “artificial intelligence” coming “out of the box” from an operating system. No service fee … just what should be happening from big players down to users on the Internet. It should be applauded, rather than suspected regarding “kludginess”, because the software basis is free, in contrast to the squillions of services popping up that are far from free.

Anyway, you can try downloading our changed macos_say_record.php PHP Voiceover inhouse web application to a local macOS Apache/PHP/MySql web server such as MAMP to see where we are going with all this, when choosing one of the “say” dropdown options, via …


HTTP://localhost:8888/macos_say_record.php

… say?!


Previous relevant Text to Speech macOS Say Large Data Tutorial is shown below.

Text to Speech macOS Say Large Data Tutorial

Text to Speech macOS Say Large Data Tutorial

So far, it seems, until today, and we were surprised, we’d only been thinking ….

  • Text to Speech macOS say … usage, and expecting success with … Small Amounts of Data … but today, with a future plan in mind we announce …
  • Text to Speech macOS say Large Data Mark I

… where you feed the wonderful macOS say command a whole block of code, say?! We did this in all innocence earlier today and … gasp … it failed.

Since then though, we’ve chipped away at some of the issues and discovered two ideas …

  1. for huge amounts of data the macOS say command has a useful …

    -f [inputFileName]

    … switch idea and for …
  2. command lines avoiding the use of ” or ‘ initial delimitation we can use backslash character escaping for those ascii characters less than (32 for) space

There’s more to “large data” issues in this our changed macos_say_record.php PHP Voiceover inhouse web application (that we last talked about with Haiku Image Tutorial) than this start today, but it is an encouraging start for our idea’s progression.

Why do we mention macOS when our public web server is Linux, in terms of operating systems? Yes, this work presupposes you have a macOS operating system in your life, because that is where you see the …


say

… command in its natural environment. Not a pretty sight at times …

Down, I say. “Say”, I down.

… but if you stick to the correct feeding times, well … you may just reap the benefits on a local Apache/PHP/MySql web server environment such as MAMP where we have our macos_say_record.php accessing passthru or exec accessing say via URL …


HTTP://localhost:8888/macos_say_record.php

… where the macOS “out of the box” say command, among other Voiceover ideas, is in play as the great Text to Speech tool that it is.


Previous relevant Haiku Image Tutorial is shown below.

Haiku Image Tutorial

Haiku Image Tutorial

Were you around when Python Cowsay API Cartoon Speech Media Tutorial‘s “genesis tutorial” called Python Cowsay API Primer Tutorial intimated …

… with an integration purpose in mind

? And then, sometime between then and now were you a “Doubting Thomas” thinking we’d forgotten about that statement? And while we’re at it, where were you on February 6, 2025 03:01 AEST?

I’m conflicted if your answers are “No” and “Robbing a bank” but, be that as it may, “we did have an integration purpose in mind” and we’ve come back to it via Haiku poetry, and a web application we wrote some time ago regarding them, and it interfaced to the theme of “the integration purpose in mind” … well you had to be there, said Putricia?!

Yes, it’s the case that hoping for the umpteenth re-researching whether anything manageable Linux wise can match what the great macOS say command has done for Speech to Text relations since Audrey Hepburn’s speech … and coming back with a “No” yet again … we started looking at it a bit more laterally and thought 😜😜 …

But what would the Cow say?

But seriously, no, we just stumbled onto the wonderful cowsay Python API / Command-line tool and wanted to … thinking laterally … have “cowsay” smarts be included into our changed macos_say_record.php PHP Voiceover inhouse web application, itself interfaced to by our changed haiku_animated_gif.html Haiku creating inhouse web application you can also try below …

… so that our changed latest draft can interface in a popup window scenario.


Previous relevant Python Cowsay API Cartoon Speech Media Tutorial is shown below.

Python Cowsay API Cartoon Speech Media Tutorial

Python Cowsay API Cartoon Speech Media Tutorial

As soon as a web application talks about image slides, as we have been dealing with allowing for the creation of cartoons with our recent cowsay Python API / Command-line tool interfacing PHP web application, maybe as Louis Lumière did many years ago, it brings out media thoughts regarding “moving pictures”. We use, here, at our RJM Programming AlmaLinux web server, the great Open Source ffmpeg to help create such media, in today’s case …

  • video
  • animated GIF

… productions using those image slides created via the (again, Open Source) cowsay Python API / Command-line tool …

<?php

if (isset($_GET['getvideo'])) {
$lenv='1';
if (isset($_GET['len'])) {
$lenv=$_GET['len'];
}
if ($_GET['getvideo'] == '1' && $lenv == '0') {
echo "<html><body onload=\" if (parent.document.getElementById('divvideo')) { parent.document.getElementById('divvideo').innerHTML='<video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video>'; } else if (parent.document.getElementById('mysource')) { parent.document.getElementById('mysource').src='data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pvd>Video version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><div id=divvideo><video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video></div>'; } setTimeout(function(){ parent.document.getElementById('pvd').scrollIntoView(); }, 2000); \"></body></html>";
} else {
if (file_exists('/tmp/video' . server_remote_addr() . '.mp4')) {
unlink('/tmp/video' . server_remote_addr() . '.mp4');
}
exec('ffmpeg -framerate 2 -i /tmp/slide_' . server_remote_addr() . '-%03d.png -vcodec libx264 -crf 22 /tmp/video' . server_remote_addr() . '.mp4');
echo "<html><body onload=\" if (parent.document.getElementById('divvideo')) { parent.document.getElementById('divvideo').innerHTML='<video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video>'; } else if (parent.document.getElementById('mysource')) { parent.document.getElementById('mysource').src='data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pvd>Video version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><div id=divvideo><video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video></div>'; } setTimeout(function(){ parent.document.getElementById('pvd').scrollIntoView(); }, 2000); \"></body></html>";
}
exit;
} else if (isset($_GET['getagif'])) {
$lenv='1';
if (isset($_GET['len'])) {
$lenv=$_GET['len'];
}
if ($_GET['getvideo'] == '1' && $lenv == '0') {
echo "<html><body onload=\" if (parent.document.getElementById('mygif')) { parent.document.getElementById('mygif').src='data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pag>Animated GIF version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><img id=mygif src=data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "></img>'; } setTimeout(function(){ parent.document.getElementById('pag').scrollIntoView(); }, 2000); \"></body></html>";
} else {
if (file_exists('/tmp/agif' . server_remote_addr() . '.gif')) {
unlink('/tmp/agif' . server_remote_addr() . '.gif');
}
exec('ffmpeg -framerate 2 -i /tmp/slide_' . server_remote_addr() . '-%03d.png /tmp/agif' . server_remote_addr() . '.gif');
echo "<html><body onload=\" if (parent.document.getElementById('mygif')) { parent.document.getElementById('mygif').src='data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pag>Animated GIF version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><img id=mygif src=data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "></img>'; } setTimeout(function(){ parent.document.getElementById('pag').scrollIntoView(); }, 2000); \"></body></html>";
}
exit;
}

?>

… as a new optional piece of additional functionality offered in our changed “fifth draft” (picking up from Python Cowsay API Cartoon Speech Content Tutorial‘s fourth draft, and further to yesterday’s Text to Image via ImageMagick Primer Tutorial) Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Text to Image via ImageMagick Primer Tutorial is shown below.

Text to Image via ImageMagick Primer Tutorial

Text to Image via ImageMagick Primer Tutorial

Why would a “Primer” tutorial point at a “well along the way” one? Well, a few reasons really …

Yes, the great ImageMagick (and we’re using it’s command line “convert” command here to make this happen) can convert text to images (ie. HTML img elements). Now, we’re not saying you always get perfect matches here, but it is akin to mere mortal dreamers think of as “intelligent scanning”. So, we wanted to have this sidetrack, and we will be resuming “normal transmission” shortly?!

We’ll leave you with some cowsay.php new relevant PHP code to ponder …

<?php

if (isset($_GET['fontlist'])) {
$selpop='';
if (!file_exists('/tmp/imfl.txt')) {
exec('convert -list font > /tmp/imfl.txt');
}
$fcont=file_get_contents('/tmp/imfl.txt');
if (strpos($fcont, 'family: ') !== false) {
$fcs=explode('family: ', $fcont);
for ($iuy=1; $iuy<sizeof($fcs); $iuy++) {
if (strpos($selpop, '>' . explode("\n", $fcs[$iuy])[0] . '<') === false) {
$selpop.="\n selo.innerHTML+='<option value=' + String.fromCharCode(39) + '" . explode("\n", $fcs[$iuy])[0] . "' + String.fromCharCode(39) + '>" . explode("\n", $fcs[$iuy])[0] . "</option>'; \n";
}
}
if ($selpop != '') {
echo "<html><body onload=\" var selos=parent.document.getElementsByTagName('select'); if (eval('' + selos.length) > 0) { var selo=selos[eval(-1 + selos.length)]; " . $selpop . " selo.style.display='inline-block'; selo.style.backgroundColor='#f0f0f0'; } \"></body></html>";
}
}
exit;
} else if (isset($_POST['text'])) {
$perlemoji='';
$emojilabbit="@- "; // vs perl
$iex='png';
$fnt='Courier';
$wdt='800';
$hgt='800';
$psiz='36';
$fcol='black';
$bcol='white';
if (isset($_POST['ext'])) { $iex=str_replace('+',' ',urldecode($_POST['ext'])); }
if (isset($_POST['ffam'])) { $fnt=str_replace('+',' ',urldecode($_POST['ffam'])); }
if (isset($_POST['width'])) { $pwdt=str_replace('+',' ',urldecode($_POST['width'])); }
if (isset($_POST['height'])) { $hgt=str_replace('+',' ',urldecode($_POST['height'])); }
if (isset($_POST['ptsize'])) { $psiz=str_replace('+',' ',urldecode($_POST['ptsize'])); }
if (isset($_POST['fcol'])) { $fcol=str_replace('+',' ',urldecode($_POST['fcol'])); }
if (isset($_POST['bcol'])) { $bcol=str_replace('+',' ',urldecode($_POST['bcol'])); }
$slidename='/tmp/imagerequest_' . server_remote_addr() . '-0.' . $iex;
file_put_contents('/tmp/imagerequest_' . server_remote_addr() . '-0.txt', str_replace('+',' ',urldecode($_POST['text'])));
file_put_contents('/tmp/maybeemojisP.txt', htmlspecialchars(str_replace('+',' ',urldecode($_POST['text'])), ENT_COMPAT,'UTF-8', true));
// yes no &#129684;
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false || strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) { // thanks to https://usage.imagemagick.org/text/#unicode
$outsofar=''; // '\x{201C}Unicode \x{2018}\x{263A}\x{2019} Please\x{201D}'
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_POST['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
} else if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_POST['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
}
$labbit=$emojilabbit;
$perlemoji="perl -e 'binmode(STDOUT, \":utf8\"); print \"" . str_replace("\n", "\x{000A}", $outsofar) . '";' . "' | ";
}
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), "\\") !== false) {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" '; }
file_put_contents('/tmp/imag.cmd', $perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
} else {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt)' . '" '; }
file_put_contents('/tmp/imaG.cmd', $perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename . ' ; chmod 777 ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
}
if (isset($_POST['raw'])) {
header('Content-Type: image/' . $iex);
echo file_get_contents($slidename);
unlink($slidename);
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
exit;
} else {
echo "<html>
<body onload=\"
if (window.parent != window.self) {
var cnvs=parent.document.getElementsByTagName('canvas');
if (eval('' + cnvs.length) > 0) {
var imgsis=new Image();
imgsis.onload=function(event){
var canvasis=cnvs[0];
var cntxis=canvasis.getContext('2d');
cntxis.drawImage(event.target, 0, 0);
};
imgsis.src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else {
var imgs=parent.document.getElementsByTagName('img');
if (eval('' + imgs.length) > 0) {
imgs[0].src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
}
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
\"></body></html>";
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
try {
unlink($slidename);
} catch(Exception $esdw) { }
}
exit;
} else if (isset($_GET['text'])) {
$perlemoji='';
$emojilabbit="@- "; // vs perl
$iex='png';
$fnt='Courier';
$wdt='800';
$hgt='800';
$psiz='36';
$fcol='black';
$bcol='white';
if (isset($_GET['ext'])) { $iex=str_replace('+',' ',urldecode($_GET['ext'])); }
if (isset($_GET['ffam'])) { $fnt=str_replace('+',' ',urldecode($_GET['ffam'])); }
if (isset($_GET['width'])) { $pwdt=str_replace('+',' ',urldecode($_GET['width'])); }
if (isset($_GET['height'])) { $hgt=str_replace('+',' ',urldecode($_GET['height'])); }
if (isset($_GET['ptsize'])) { $psiz=str_replace('+',' ',urldecode($_GET['ptsize'])); }
if (isset($_GET['fcol'])) { $fcol=str_replace('+',' ',urldecode($_GET['fcol'])); }
if (isset($_GET['bcol'])) { $bcol=str_replace('+',' ',urldecode($_GET['bcol'])); }
$slidename='/tmp/imagerequest_' . server_remote_addr() . '-0.' . $iex;
file_put_contents('/tmp/imagerequest_' . server_remote_addr() . '-0.txt', str_replace('+',' ',urldecode($_GET['text'])));
file_put_contents('/tmp/maybeemojisG.txt', htmlspecialchars(str_replace('+',' ',urldecode($_GET['text'])), ENT_COMPAT,'UTF-8', true));
// yes no &#129684;
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false || strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) { // thanks to https://usage.imagemagick.org/text/#unicode
$outsofar=''; // '\x{201C}Unicode \x{2018}\x{263A}\x{2019} Please\x{201D}'
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_GET['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
} else if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_GET['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
}
$labbit=$emojilabbit;
$perlemoji="perl -e 'binmode(STDOUT, \":utf8\"); print \"" . str_replace("\n", "\x{000A}", $outsofar) . '";' . "' | ";
}
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), "\\") !== false) {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" '; }
//file_put_contents('/tmp/imag.cmd', 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" ' . $slidename . ' ; chmod 777 ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
} else {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt)' . '" '; }
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
}
if (isset($_GET['raw'])) {
header('Content-Type: image/' . $iex);
echo file_get_contents($slidename);
unlink($slidename);
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
exit;
} else {
echo "<html>
<body onload=\"
if (window.parent != window.self) {
var cnvs=parent.document.getElementsByTagName('canvas');
if (eval('' + cnvs.length) > 0) {
var imgsis=new Image();
imgsis.onload=function(event){
var canvasis=cnvs[0];
var cntxis=canvasis.getContext('2d');
cntxis.drawImage(event.target, 0, 0);
};
imgsis.src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else {
var imgs=parent.document.getElementsByTagName('img');
if (eval('' + imgs.length) > 0) {
imgs[0].src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
}
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
\"></body></html>";
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
try {
unlink($slidename);
} catch(Exception $esdw) { }
}
exit;
}

?>


Previous relevant Python Cowsay API Cartoon Speech Content Tutorial is shown below.

Python Cowsay API Cartoon Speech Content Tutorial

Python Cowsay API Cartoon Speech Content Tutorial

If you were to ask most people what is more onerous filling in online web forms on the way to making something happen …

  • we’re guessing, rather than saying button presses
  • we’re guessing, they’re more likely to say typing out text …

… with it’s associated tabbing out to negotiate as well. But, supposing we could offer you a “speech to text” approach to performing “typing out text” in our latest cowsay Python API / Command-line tool interfacing PHP web application?

For some years now, we’ve interfaced to a …

  • non-mobile
  • Google Chrome
  • secure URL via https: protocol
  • allowing access to microphone

… means by which we normally access via a “top” hierarchy level call to our inhouse Google Speech to Text API interfacing web application helper.

Isn’t a popup window awkward here? Well, you might think so, but today, we discovered with the Google Chrome browser we used on macOS …

  • we initially call our inhouse Google Speech to Text API interfacing web application helper as a popup sitting in front of the cowsay interfacing parent window …
    <?php echo ”

    function anop() {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    topwo=window_open('https://www.google.com/intl/en/chrome/demos/speech.html','_blank','top=120,left=' + eval(eval('' + screen.width) - 690) + ',width=690,height=550');
    setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000);
    setInterval(function(){ if (!topwo.closed) { topwo.focus(); } topwo.location.href='https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4'; setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000); }, 30000);
    } else {
    topwo=window.open('https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4','_blank','top=120,left=' + eval(eval('' + screen.width) - 690) + ',width=690,height=550');
    setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000);
    setInterval(function(){ if (!topwo.closed) { topwo.focus(); } topwo.location.href='https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4'; setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000); }, 30000);
    }
    }

    “; ?>
  • and found that it was visible until any click or focus back to the cowsay interfacing parent window … normally an annoyance …
  • but not if …
    1. we semi regularly reload the our inhouse Google Speech to Text API interfacing web application helper … to refresh it’s red “recording” button instigation … and then …
    2. even if it remains hidden, it is still apparent to the focussed cowsay interfacing parent window on account of an orange “microphone on recording” icon appearing for the Google Chrome web browser user up at it’s Menu Bar … and …
    3. audio being “sight independent” the user does not have to refocus our inhouse Google Speech to Text API interfacing web application helper, just talk into the microphone just after that new icon appears … so that …
    4. the Google Speech to Text smarts help transfer that resultant text over to the textarea of the cowsay interfacing parent window, even avoiding any need to tab out of that textarea element … ahead of …
    5. the rest of the dropdown selections and button presses needed to achieve the user aim of establishing a new slide, perhaps for a Cartoon being created

… you can see happening with today’s animated GIF presentation on top of the work of yesterday’s Python Cowsay API Cartoon Tutorial in our changed “fourth draft” Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Python Cowsay API Cartoon Tutorial is shown below.

Python Cowsay API Cartoon Tutorial

Python Cowsay API Cartoon Tutorial

We’ve long been interested in online web application ideas that end up with a half decent cartoon the user can create, and share, themselves. “Half decent” becomes “fully decent” with a user who has a great imagination. And so, onto yesterday’s Python Cowsay API Primer Tutorial‘s start with interfacing to the great cowsay Python API / Command-line tool we access via the PHP exec method conduit to our AlmaLinux Apache/PHP/MySql Linux web server, today we’ve extended that …

  • “proof of concept” thinking … onto …
  • cartoon creation “smarts” … starting with (also egged on here by mobile platform problems with monospaced fonts, it seems like)
  • allowing a tabular display of our cowsay components … into …
  • table cells horizontally aligned (and so, less vulnerable to monospacing inaccuracies) … also allowing …
  • within any table cell there is a topmost th table cell wording part above a cowsay character td cell lower part …
  • “half decent” looking via static CSS
    <?php echo ”

    <style>
    margin: 0 0 0 0;
    padding: 0 0 0 0;
    tr { vertical-align: top; }
    td { vertical-align: top; }
    th { vertical-align: top; }

    * { font-family:'Courier New',Courier,monospace; }
    .img-hor { // thanks to https://stackoverflow.com/questions/32875695/flip-mirror-an-image-horizontally-vertically-with-css
    -moz-transform: scaleX(-1);
    -o-transform: scaleX(-1);
    -webkit-transform: scaleX(-1);
    transform: scaleX(-1);
    filter: FlipH;
    -ms-filter: 'FlipH';
    }
    .img-ver { // thanks to https://stackoverflow.com/questions/32875695/flip-mirror-an-image-horizontally-vertically-with-css
    -moz-transform: scaleY(-1);
    -o-transform: scaleY(-1);
    -webkit-transform: scaleY(-1);
    transform: scaleY(-1);
    filter: FlipV;
    -ms-filter: 'FlipV';
    }

    .glow {
    -webkit-animation: glow 1s linear infinite alternate;
    -moz-animation: glow 1s linear infinite alternate;
    animation: glow 1s linear infinite alternate;
    }

    /* Thanks to https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_glowing_text */

    @-webkit-keyframes glow {
    from {
    box-shadow: 0 0 3px #fff, 0 0 5px #fff, 0 0 37px #e60073, 0 0 9px #e60073, 0 0 11px #e60073, 0 0 13px #e60073, 0 0 15px #e60073;
    }

    to {
    box-shadow: 0 0 24px #fff, 0 0 6px #ff4da6, 0 0 8px #ff4da6, 0 0 10px #ff4da6, 0 0 12px #ff4da6, 0 0 14px #ff4da6, 0 0 16px #ff4da6;
    }
    }

    th[id$='0'] {
    background: rgba(224,240,240,0.6); //#e0f0f0;
    }

    th[id$='1'] {
    background: rgba(225,241,241,0.6); //#e1f1f1;
    }

    th[id$='2'] {
    background: rgba(226,242,242,0.6); //#e2f2f2;
    }

    th[id$='3'] {
    background: rgba(227,243,243,0.6); //#e3f3f3;
    }

    th[id$='4'] {
    background: rgba(228,244,244,0.6); //#e4f4f4;
    }

    th[id$='5'] {
    background: rgba(229,245,245,0.6); //#e5f5f5;
    }

    th[id$='6'] {
    background: rgba(230,246,246,0.6); //#e6f6f6;
    }

    th[id$='7'] {
    background: rgba(231,247,247,0.6); //#e7f7f7;
    }

    th[id$='8'] {
    background: rgba(232,248,248,0.6); //#e2f2f2;
    }

    th[id$='9'] {
    background: rgba(233,249,249,0.6); //#e9f9f9;
    }

    td[id$='0'] {
    background: rgba(240,240,240,0.3); //#f0f0f0;
    text-shadow:-1px 1px 1px #ff2d90;
    }

    td[id$='1'] {
    background: rgba(241,241,241,0.3); //#f1f1f1;
    text-shadow:-1px 1px 1px #ff2d91;
    float: bottom;
    }

    td[id$='2'] {
    background: rgba(242,242,242,0.3); //#f2f2f2;
    text-shadow:-1px 1px 1px #ff2d92;
    }

    td[id$='3'] {
    background: rgba(243,243,243,0.3); //#f3f3f3;
    text-shadow:-1px 1px 1px #ff2d93;
    }

    td[id$='4'] {
    background: rgba(244,244,244,0.3); //#f4f4f4;
    text-shadow:-1px 1px 1px #ff2d94;
    }

    td[id$='5'] {
    background: rgba(245,245,245,0.3); //#f5f5f5;
    text-shadow:-1px 1px 1px #ff2d95;
    }

    td[id$='6'] {
    background: rgba(246,246,246,0.3); //#f6f6f6;
    text-shadow:-1px 1px 1px #ff2d96;
    }

    td[id$='7'] {
    background: rgba(247,247,247,0.3); //#f7f7f7;
    text-shadow:-1px 1px 1px #ff2d97;
    }

    td[id$='8'] {
    background: rgba(248,248,248,0.3); //#f8f8f8;
    text-shadow:-1px 1px 1px #ff2d98;
    }

    td[id$='9'] {
    background: rgba(249,249,249,0.3); //#f9f9f9;
    text-shadow:-1px 1px 1px #ff2d99;
    }

    table tbody tr:first-child {
    background: transparent; //#f6f6e6;
    }
    </style>

    “; ?>
    … and then …
  • whenever new cell content happens padding-top adding CSS Javascript DOM nuanced display logic via …
    <?php echo ”

    function paddingtopit() {
    var maxtwo=0, thistwo=0;
    var thhs=[], tdhs=[], it=0;
    var thdids=[];
    //trthtd1
    //trtdtd1
    var tds=document.getElementsByTagName('td');
    for (it=0; it<tds.length; it++) {
    if (('' + tds[it].id).indexOf('trtdtd') != -1) {
    if (('' + tds[it].style.paddingTop).replace(/^null/g,'').replace(/^undefined/g,'').trim() != '') {
    tds[it].style.paddingTop='0px';
    }
    }
    }
    for (it=0; it<tds.length; it++) {
    if (('' + tds[it].id).indexOf('trtdtd') != -1) {
    tdhs.push(eval('' + tds[it].getBoundingClientRect().height));
    thdids.push('' + tds[it].id);
    }
    }
    var ths=document.getElementsByTagName('th');
    for (it=0; it<ths.length; it++) {
    if (('' + ths[it].id).indexOf('trthtd') != -1) {
    thhs.push(eval('' + ths[it].getBoundingClientRect().height));
    thistwo=eval(thhs[it] + tdhs[it]);
    if (thistwo > maxtwo) { maxtwo=thistwo; }
    }
    }
    for (it=0; it<tdhs.length; it++) {
    thistwo=eval(thhs[it] + tdhs[it]);
    if (thistwo < maxtwo) {
    document.getElementById(thdids[it]).style.paddingTop='' + eval(maxtwo - thistwo) + 'px';
    }
    }
    }

    “; ?>
    … so that …
  • cartoons present with “speech bubble” wording aligned to the top in our “cells” (ie. th contenteditable=true editable wording on top of td horizontal flip (double click) and/or vertical flop (right click) editable lower part) with those characters aligned to the bottom

… in our changed “third draft” Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Python Cowsay API Primer Tutorial is shown below.

Python Cowsay API Primer Tutorial

Python Cowsay API Primer Tutorial

We discovered an interesting Open Source Python API / Command-line tool called cowsay which we installed up at our AlmaLinux web server via …


pip install cowsay

… with an integration purpose in mind, so thanks. Before many readers’ time indeed, but some may remember those cute banner printouts that told you who owned the next printout on a spooling “crude graphics” printout in the late 70’s … well cowsay encapsulates those heady days (and who can forget punch cards)?! Before integration, though, we want to test it via a new PHP supervisor on exec method Linux command line interfacings to cowsay.

So we started, with this “first draft” getting places and then this “second draft” with a little more sophistication to leave the day with this interfacer

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in Ajax, eLearning, Event-Driven Programming, Operating System, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Text to Speech macOS Say Large Data Sharing Tutorial

Text to Speech macOS Say Large Data Sharing Tutorial

Text to Speech macOS Say Large Data Sharing Tutorial

Part of improving a web application regarding “large data” is offering some sharing functionality for “large data” scenarios, but this project we have learnt, it being unique regarding the “macOS only say” aspects to it, have taught us not to go overboard trying to cater for everything here. Yesterday’s Text to Speech macOS Say Large Data Tutorial got us started regarding “large data” scenarios where it was just designed for the single user usage. This does not require the transfer of data from that macOS local web browser environment up to a pubic website (Linux) web server environment, involving audio files that can become too large for comfort, often, here.

Our biggest dilemma in this work was, so far in testing we found, only the Firefox web browser would accept either of …

  • “a” “mailto:” link of too big a length involving the audio data URI contained in a hashtag, initiated from localhost MAMP environment
  • call of public website version of macos_say_record.php involving the audio data URI contained in a hashtag, initiated from localhost MAMP environment

… else the all too common …


about:blank#blocked

… would stymie our efforts in “large data” scenarios, where audio data URIs appear within the email link URL hashtag part. Guess we just lost 80% of the audience (except if we tell you now we rely less on audio data URIs appearing within the email link URL hashtag part). But we really wish users would not get spooked by seeing “about:blank#blocked” and think there is anything sinister necessarily, but rather try new web browsers, and try new ways of using free tools. What we are trying to show here, in a free way, is a bit of a way in to some aspects of what people refer to as “artificial intelligence” coming “out of the box” from an operating system. No service fee … just what should be happening from big players down to users on the Internet. It should be applauded, rather than suspected regarding “kludginess”, because the software basis is free, in contrast to the squillions of services popping up that are far from free.

Anyway, you can try downloading our changed macos_say_record.php PHP Voiceover inhouse web application to a local macOS Apache/PHP/MySql web server such as MAMP to see where we are going with all this, when choosing one of the “say” dropdown options, via …


HTTP://localhost:8888/macos_say_record.php

… say?!


Previous relevant Text to Speech macOS Say Large Data Tutorial is shown below.

Text to Speech macOS Say Large Data Tutorial

Text to Speech macOS Say Large Data Tutorial

So far, it seems, until today, and we were surprised, we’d only been thinking ….

  • Text to Speech macOS say … usage, and expecting success with … Small Amounts of Data … but today, with a future plan in mind we announce …
  • Text to Speech macOS say Large Data Mark I

… where you feed the wonderful macOS say command a whole block of code, say?! We did this in all innocence earlier today and … gasp … it failed.

Since then though, we’ve chipped away at some of the issues and discovered two ideas …

  1. for huge amounts of data the macOS say command has a useful …

    -f [inputFileName]

    … switch idea and for …
  2. command lines avoiding the use of ” or ‘ initial delimitation we can use backslash character escaping for those ascii characters less than (32 for) space

There’s more to “large data” issues in this our changed macos_say_record.php PHP Voiceover inhouse web application (that we last talked about with Haiku Image Tutorial) than this start today, but it is an encouraging start for our idea’s progression.

Why do we mention macOS when our public web server is Linux, in terms of operating systems? Yes, this work presupposes you have a macOS operating system in your life, because that is where you see the …


say

… command in its natural environment. Not a pretty sight at times …

Down, I say. “Say”, I down.

… but if you stick to the correct feeding times, well … you may just reap the benefits on a local Apache/PHP/MySql web server environment such as MAMP where we have our macos_say_record.php accessing passthru or exec accessing say via URL …


HTTP://localhost:8888/macos_say_record.php

… where the macOS “out of the box” say command, among other Voiceover ideas, is in play as the great Text to Speech tool that it is.


Previous relevant Haiku Image Tutorial is shown below.

Haiku Image Tutorial

Haiku Image Tutorial

Were you around when Python Cowsay API Cartoon Speech Media Tutorial‘s “genesis tutorial” called Python Cowsay API Primer Tutorial intimated …

… with an integration purpose in mind

? And then, sometime between then and now were you a “Doubting Thomas” thinking we’d forgotten about that statement? And while we’re at it, where were you on February 6, 2025 03:01 AEST?

I’m conflicted if your answers are “No” and “Robbing a bank” but, be that as it may, “we did have an integration purpose in mind” and we’ve come back to it via Haiku poetry, and a web application we wrote some time ago regarding them, and it interfaced to the theme of “the integration purpose in mind” … well you had to be there, said Putricia?!

Yes, it’s the case that hoping for the umpteenth re-researching whether anything manageable Linux wise can match what the great macOS say command has done for Speech to Text relations since Audrey Hepburn’s speech … and coming back with a “No” yet again … we started looking at it a bit more laterally and thought 😜😜 …

But what would the Cow say?

But seriously, no, we just stumbled onto the wonderful cowsay Python API / Command-line tool and wanted to … thinking laterally … have “cowsay” smarts be included into our changed macos_say_record.php PHP Voiceover inhouse web application, itself interfaced to by our changed haiku_animated_gif.html Haiku creating inhouse web application you can also try below …

… so that our changed latest draft can interface in a popup window scenario.


Previous relevant Python Cowsay API Cartoon Speech Media Tutorial is shown below.

Python Cowsay API Cartoon Speech Media Tutorial

Python Cowsay API Cartoon Speech Media Tutorial

As soon as a web application talks about image slides, as we have been dealing with allowing for the creation of cartoons with our recent cowsay Python API / Command-line tool interfacing PHP web application, maybe as Louis Lumière did many years ago, it brings out media thoughts regarding “moving pictures”. We use, here, at our RJM Programming AlmaLinux web server, the great Open Source ffmpeg to help create such media, in today’s case …

  • video
  • animated GIF

… productions using those image slides created via the (again, Open Source) cowsay Python API / Command-line tool …

<?php

if (isset($_GET['getvideo'])) {
$lenv='1';
if (isset($_GET['len'])) {
$lenv=$_GET['len'];
}
if ($_GET['getvideo'] == '1' && $lenv == '0') {
echo "<html><body onload=\" if (parent.document.getElementById('divvideo')) { parent.document.getElementById('divvideo').innerHTML='<video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video>'; } else if (parent.document.getElementById('mysource')) { parent.document.getElementById('mysource').src='data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pvd>Video version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><div id=divvideo><video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video></div>'; } setTimeout(function(){ parent.document.getElementById('pvd').scrollIntoView(); }, 2000); \"></body></html>";
} else {
if (file_exists('/tmp/video' . server_remote_addr() . '.mp4')) {
unlink('/tmp/video' . server_remote_addr() . '.mp4');
}
exec('ffmpeg -framerate 2 -i /tmp/slide_' . server_remote_addr() . '-%03d.png -vcodec libx264 -crf 22 /tmp/video' . server_remote_addr() . '.mp4');
echo "<html><body onload=\" if (parent.document.getElementById('divvideo')) { parent.document.getElementById('divvideo').innerHTML='<video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video>'; } else if (parent.document.getElementById('mysource')) { parent.document.getElementById('mysource').src='data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pvd>Video version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><div id=divvideo><video id=myvideo controls><source id=mysource type=video/mp4 src=' + String.fromCharCode(39) + 'data:video/mp4;base64," . base64_encode(file_get_contents('/tmp/video' . server_remote_addr() . '.mp4')) . "' + String.fromCharCode(39) + '></source></video></div>'; } setTimeout(function(){ parent.document.getElementById('pvd').scrollIntoView(); }, 2000); \"></body></html>";
}
exit;
} else if (isset($_GET['getagif'])) {
$lenv='1';
if (isset($_GET['len'])) {
$lenv=$_GET['len'];
}
if ($_GET['getvideo'] == '1' && $lenv == '0') {
echo "<html><body onload=\" if (parent.document.getElementById('mygif')) { parent.document.getElementById('mygif').src='data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pag>Animated GIF version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><img id=mygif src=data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "></img>'; } setTimeout(function(){ parent.document.getElementById('pag').scrollIntoView(); }, 2000); \"></body></html>";
} else {
if (file_exists('/tmp/agif' . server_remote_addr() . '.gif')) {
unlink('/tmp/agif' . server_remote_addr() . '.gif');
}
exec('ffmpeg -framerate 2 -i /tmp/slide_' . server_remote_addr() . '-%03d.png /tmp/agif' . server_remote_addr() . '.gif');
echo "<html><body onload=\" if (parent.document.getElementById('mygif')) { parent.document.getElementById('mygif').src='data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "'; } else { parent.document.getElementById('divmedia').innerHTML+='<br><br><p id=pag>Animated GIF version below ... <a style=display:inline-block; href=#myh1>Back to top ...</a></p><br><img id=mygif src=data:image/gif;base64," . base64_encode(file_get_contents('/tmp/agif' . server_remote_addr() . '.gif')) . "></img>'; } setTimeout(function(){ parent.document.getElementById('pag').scrollIntoView(); }, 2000); \"></body></html>";
}
exit;
}

?>

… as a new optional piece of additional functionality offered in our changed “fifth draft” (picking up from Python Cowsay API Cartoon Speech Content Tutorial‘s fourth draft, and further to yesterday’s Text to Image via ImageMagick Primer Tutorial) Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Text to Image via ImageMagick Primer Tutorial is shown below.

Text to Image via ImageMagick Primer Tutorial

Text to Image via ImageMagick Primer Tutorial

Why would a “Primer” tutorial point at a “well along the way” one? Well, a few reasons really …

Yes, the great ImageMagick (and we’re using it’s command line “convert” command here to make this happen) can convert text to images (ie. HTML img elements). Now, we’re not saying you always get perfect matches here, but it is akin to mere mortal dreamers think of as “intelligent scanning”. So, we wanted to have this sidetrack, and we will be resuming “normal transmission” shortly?!

We’ll leave you with some cowsay.php new relevant PHP code to ponder …

<?php

if (isset($_GET['fontlist'])) {
$selpop='';
if (!file_exists('/tmp/imfl.txt')) {
exec('convert -list font > /tmp/imfl.txt');
}
$fcont=file_get_contents('/tmp/imfl.txt');
if (strpos($fcont, 'family: ') !== false) {
$fcs=explode('family: ', $fcont);
for ($iuy=1; $iuy<sizeof($fcs); $iuy++) {
if (strpos($selpop, '>' . explode("\n", $fcs[$iuy])[0] . '<') === false) {
$selpop.="\n selo.innerHTML+='<option value=' + String.fromCharCode(39) + '" . explode("\n", $fcs[$iuy])[0] . "' + String.fromCharCode(39) + '>" . explode("\n", $fcs[$iuy])[0] . "</option>'; \n";
}
}
if ($selpop != '') {
echo "<html><body onload=\" var selos=parent.document.getElementsByTagName('select'); if (eval('' + selos.length) > 0) { var selo=selos[eval(-1 + selos.length)]; " . $selpop . " selo.style.display='inline-block'; selo.style.backgroundColor='#f0f0f0'; } \"></body></html>";
}
}
exit;
} else if (isset($_POST['text'])) {
$perlemoji='';
$emojilabbit="@- "; // vs perl
$iex='png';
$fnt='Courier';
$wdt='800';
$hgt='800';
$psiz='36';
$fcol='black';
$bcol='white';
if (isset($_POST['ext'])) { $iex=str_replace('+',' ',urldecode($_POST['ext'])); }
if (isset($_POST['ffam'])) { $fnt=str_replace('+',' ',urldecode($_POST['ffam'])); }
if (isset($_POST['width'])) { $pwdt=str_replace('+',' ',urldecode($_POST['width'])); }
if (isset($_POST['height'])) { $hgt=str_replace('+',' ',urldecode($_POST['height'])); }
if (isset($_POST['ptsize'])) { $psiz=str_replace('+',' ',urldecode($_POST['ptsize'])); }
if (isset($_POST['fcol'])) { $fcol=str_replace('+',' ',urldecode($_POST['fcol'])); }
if (isset($_POST['bcol'])) { $bcol=str_replace('+',' ',urldecode($_POST['bcol'])); }
$slidename='/tmp/imagerequest_' . server_remote_addr() . '-0.' . $iex;
file_put_contents('/tmp/imagerequest_' . server_remote_addr() . '-0.txt', str_replace('+',' ',urldecode($_POST['text'])));
file_put_contents('/tmp/maybeemojisP.txt', htmlspecialchars(str_replace('+',' ',urldecode($_POST['text'])), ENT_COMPAT,'UTF-8', true));
// yes no &#129684;
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false || strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) { // thanks to https://usage.imagemagick.org/text/#unicode
$outsofar=''; // '\x{201C}Unicode \x{2018}\x{263A}\x{2019} Please\x{201D}'
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_POST['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
} else if (strpos(str_replace('+',' ',urldecode($_POST['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_POST['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
}
$labbit=$emojilabbit;
$perlemoji="perl -e 'binmode(STDOUT, \":utf8\"); print \"" . str_replace("\n", "\x{000A}", $outsofar) . '";' . "' | ";
}
if (strpos(str_replace('+',' ',urldecode($_POST['text'])), "\\") !== false) {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" '; }
file_put_contents('/tmp/imag.cmd', $perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
} else {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt)' . '" '; }
file_put_contents('/tmp/imaG.cmd', $perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename . ' ; chmod 777 ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
}
if (isset($_POST['raw'])) {
header('Content-Type: image/' . $iex);
echo file_get_contents($slidename);
unlink($slidename);
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
exit;
} else {
echo "<html>
<body onload=\"
if (window.parent != window.self) {
var cnvs=parent.document.getElementsByTagName('canvas');
if (eval('' + cnvs.length) > 0) {
var imgsis=new Image();
imgsis.onload=function(event){
var canvasis=cnvs[0];
var cntxis=canvasis.getContext('2d');
cntxis.drawImage(event.target, 0, 0);
};
imgsis.src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else {
var imgs=parent.document.getElementsByTagName('img');
if (eval('' + imgs.length) > 0) {
imgs[0].src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
}
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
\"></body></html>";
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
try {
unlink($slidename);
} catch(Exception $esdw) { }
}
exit;
} else if (isset($_GET['text'])) {
$perlemoji='';
$emojilabbit="@- "; // vs perl
$iex='png';
$fnt='Courier';
$wdt='800';
$hgt='800';
$psiz='36';
$fcol='black';
$bcol='white';
if (isset($_GET['ext'])) { $iex=str_replace('+',' ',urldecode($_GET['ext'])); }
if (isset($_GET['ffam'])) { $fnt=str_replace('+',' ',urldecode($_GET['ffam'])); }
if (isset($_GET['width'])) { $pwdt=str_replace('+',' ',urldecode($_GET['width'])); }
if (isset($_GET['height'])) { $hgt=str_replace('+',' ',urldecode($_GET['height'])); }
if (isset($_GET['ptsize'])) { $psiz=str_replace('+',' ',urldecode($_GET['ptsize'])); }
if (isset($_GET['fcol'])) { $fcol=str_replace('+',' ',urldecode($_GET['fcol'])); }
if (isset($_GET['bcol'])) { $bcol=str_replace('+',' ',urldecode($_GET['bcol'])); }
$slidename='/tmp/imagerequest_' . server_remote_addr() . '-0.' . $iex;
file_put_contents('/tmp/imagerequest_' . server_remote_addr() . '-0.txt', str_replace('+',' ',urldecode($_GET['text'])));
file_put_contents('/tmp/maybeemojisG.txt', htmlspecialchars(str_replace('+',' ',urldecode($_GET['text'])), ENT_COMPAT,'UTF-8', true));
// yes no &#129684;
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false || strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) { // thanks to https://usage.imagemagick.org/text/#unicode
$outsofar=''; // '\x{201C}Unicode \x{2018}\x{263A}\x{2019} Please\x{201D}'
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_GET['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
} else if (strpos(str_replace('+',' ',urldecode($_GET['text'])), '&#') !== false) {
$outs=explode('&#', str_replace('+',' ',urldecode($_GET['text'])));
$outsofar=$outs[0];
for ($ivx=1; $ivx<sizeof($outs); $ivx++) {
$decis=explode(';', $outs[$ivx])[0];
if (str_replace('0','',str_replace('1','',str_replace('2','',str_replace('3','',str_replace('4','',str_replace('5','',str_replace('6','',str_replace('7','',str_replace('8','',str_replace('9','',$decis)))))))))) != '') {
if (substr(strtolower($decis),0,1) == 'x') {
$outsofar.="\\x{" . substr($decis,1) . "}";
} else {
$outsofar.="\\x{" . $decis . "}";
}
} else {
$outsofar.="\\x{" . dechex($decis) . "}";
}
$outsofar.=substr($outs[$ivx],strlen($decis . ';'));
}
}
$labbit=$emojilabbit;
$perlemoji="perl -e 'binmode(STDOUT, \":utf8\"); print \"" . str_replace("\n", "\x{000A}", $outsofar) . '";' . "' | ";
}
if (strpos(str_replace('+',' ',urldecode($_GET['text'])), "\\") !== false) {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" '; }
//file_put_contents('/tmp/imag.cmd', 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt | ' . " sed '/\\\\/s//\\\\\\\\/g')" . '" ' . $slidename . ' ; chmod 777 ' . $slidename);
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
} else {
if ($perlemoji == '') { $labbit='"$(cat /tmp/imagerequest_' . server_remote_addr() . '-0.txt)' . '" '; }
exec($perlemoji . 'convert -background "' . $bcol . '" -fill "' . $fcol . '" -size ' . $wdt . 'x' . $hgt . ' -font ' . $fnt . ' -pointsize ' . $psiz . ' label:' . $labbit . ' ' . $slidename);
exec('chmod 777 ' . $slidename);
}
if (isset($_GET['raw'])) {
header('Content-Type: image/' . $iex);
echo file_get_contents($slidename);
unlink($slidename);
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
exit;
} else {
echo "<html>
<body onload=\"
if (window.parent != window.self) {
var cnvs=parent.document.getElementsByTagName('canvas');
if (eval('' + cnvs.length) > 0) {
var imgsis=new Image();
imgsis.onload=function(event){
var canvasis=cnvs[0];
var cntxis=canvasis.getContext('2d');
cntxis.drawImage(event.target, 0, 0);
};
imgsis.src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else {
var imgs=parent.document.getElementsByTagName('img');
if (eval('' + imgs.length) > 0) {
imgs[0].src='data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "';
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
}
} else if (document.body.innerHTML == '') {
document.body.innerHTML='<img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img><style> * { margin:0 0 0 0; padding:0 0 0 0; } img { border-top: 8px solid " . $bcol . "; }</style>';
} else {
document.body.innerHTML+='<br><img src=data:image/" . $iex . ";base64," . base64_encode(file_get_contents($slidename)) . "></img>';
}
\"></body></html>";
unlink('/tmp/imagerequest_' . server_remote_addr() . '-0.txt');
try {
unlink($slidename);
} catch(Exception $esdw) { }
}
exit;
}

?>


Previous relevant Python Cowsay API Cartoon Speech Content Tutorial is shown below.

Python Cowsay API Cartoon Speech Content Tutorial

Python Cowsay API Cartoon Speech Content Tutorial

If you were to ask most people what is more onerous filling in online web forms on the way to making something happen …

  • we’re guessing, rather than saying button presses
  • we’re guessing, they’re more likely to say typing out text …

… with it’s associated tabbing out to negotiate as well. But, supposing we could offer you a “speech to text” approach to performing “typing out text” in our latest cowsay Python API / Command-line tool interfacing PHP web application?

For some years now, we’ve interfaced to a …

  • non-mobile
  • Google Chrome
  • secure URL via https: protocol
  • allowing access to microphone

… means by which we normally access via a “top” hierarchy level call to our inhouse Google Speech to Text API interfacing web application helper.

Isn’t a popup window awkward here? Well, you might think so, but today, we discovered with the Google Chrome browser we used on macOS …

  • we initially call our inhouse Google Speech to Text API interfacing web application helper as a popup sitting in front of the cowsay interfacing parent window …
    <?php echo ”

    function anop() {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    topwo=window_open('https://www.google.com/intl/en/chrome/demos/speech.html','_blank','top=120,left=' + eval(eval('' + screen.width) - 690) + ',width=690,height=550');
    setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000);
    setInterval(function(){ if (!topwo.closed) { topwo.focus(); } topwo.location.href='https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4'; setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000); }, 30000);
    } else {
    topwo=window.open('https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4','_blank','top=120,left=' + eval(eval('' + screen.width) - 690) + ',width=690,height=550');
    setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000);
    setInterval(function(){ if (!topwo.closed) { topwo.focus(); } topwo.location.href='https://www.rjmprogramming.com.au/PHP/speech_supervisor.php?rand=' + Math.floor(Math.random() * 1987967) + '&mode=4'; setTimeout(function(){ topwo.scrollTo(0,0); topwo.document.getElementById('tdm').style.opacity='0.0'; }, 6000); }, 30000);
    }
    }

    “; ?>
  • and found that it was visible until any click or focus back to the cowsay interfacing parent window … normally an annoyance …
  • but not if …
    1. we semi regularly reload the our inhouse Google Speech to Text API interfacing web application helper … to refresh it’s red “recording” button instigation … and then …
    2. even if it remains hidden, it is still apparent to the focussed cowsay interfacing parent window on account of an orange “microphone on recording” icon appearing for the Google Chrome web browser user up at it’s Menu Bar … and …
    3. audio being “sight independent” the user does not have to refocus our inhouse Google Speech to Text API interfacing web application helper, just talk into the microphone just after that new icon appears … so that …
    4. the Google Speech to Text smarts help transfer that resultant text over to the textarea of the cowsay interfacing parent window, even avoiding any need to tab out of that textarea element … ahead of …
    5. the rest of the dropdown selections and button presses needed to achieve the user aim of establishing a new slide, perhaps for a Cartoon being created

… you can see happening with today’s animated GIF presentation on top of the work of yesterday’s Python Cowsay API Cartoon Tutorial in our changed “fourth draft” Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Python Cowsay API Cartoon Tutorial is shown below.

Python Cowsay API Cartoon Tutorial

Python Cowsay API Cartoon Tutorial

We’ve long been interested in online web application ideas that end up with a half decent cartoon the user can create, and share, themselves. “Half decent” becomes “fully decent” with a user who has a great imagination. And so, onto yesterday’s Python Cowsay API Primer Tutorial‘s start with interfacing to the great cowsay Python API / Command-line tool we access via the PHP exec method conduit to our AlmaLinux Apache/PHP/MySql Linux web server, today we’ve extended that …

  • “proof of concept” thinking … onto …
  • cartoon creation “smarts” … starting with (also egged on here by mobile platform problems with monospaced fonts, it seems like)
  • allowing a tabular display of our cowsay components … into …
  • table cells horizontally aligned (and so, less vulnerable to monospacing inaccuracies) … also allowing …
  • within any table cell there is a topmost th table cell wording part above a cowsay character td cell lower part …
  • “half decent” looking via static CSS
    <?php echo ”

    <style>
    margin: 0 0 0 0;
    padding: 0 0 0 0;
    tr { vertical-align: top; }
    td { vertical-align: top; }
    th { vertical-align: top; }

    * { font-family:'Courier New',Courier,monospace; }
    .img-hor { // thanks to https://stackoverflow.com/questions/32875695/flip-mirror-an-image-horizontally-vertically-with-css
    -moz-transform: scaleX(-1);
    -o-transform: scaleX(-1);
    -webkit-transform: scaleX(-1);
    transform: scaleX(-1);
    filter: FlipH;
    -ms-filter: 'FlipH';
    }
    .img-ver { // thanks to https://stackoverflow.com/questions/32875695/flip-mirror-an-image-horizontally-vertically-with-css
    -moz-transform: scaleY(-1);
    -o-transform: scaleY(-1);
    -webkit-transform: scaleY(-1);
    transform: scaleY(-1);
    filter: FlipV;
    -ms-filter: 'FlipV';
    }

    .glow {
    -webkit-animation: glow 1s linear infinite alternate;
    -moz-animation: glow 1s linear infinite alternate;
    animation: glow 1s linear infinite alternate;
    }

    /* Thanks to https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_glowing_text */

    @-webkit-keyframes glow {
    from {
    box-shadow: 0 0 3px #fff, 0 0 5px #fff, 0 0 37px #e60073, 0 0 9px #e60073, 0 0 11px #e60073, 0 0 13px #e60073, 0 0 15px #e60073;
    }

    to {
    box-shadow: 0 0 24px #fff, 0 0 6px #ff4da6, 0 0 8px #ff4da6, 0 0 10px #ff4da6, 0 0 12px #ff4da6, 0 0 14px #ff4da6, 0 0 16px #ff4da6;
    }
    }

    th[id$='0'] {
    background: rgba(224,240,240,0.6); //#e0f0f0;
    }

    th[id$='1'] {
    background: rgba(225,241,241,0.6); //#e1f1f1;
    }

    th[id$='2'] {
    background: rgba(226,242,242,0.6); //#e2f2f2;
    }

    th[id$='3'] {
    background: rgba(227,243,243,0.6); //#e3f3f3;
    }

    th[id$='4'] {
    background: rgba(228,244,244,0.6); //#e4f4f4;
    }

    th[id$='5'] {
    background: rgba(229,245,245,0.6); //#e5f5f5;
    }

    th[id$='6'] {
    background: rgba(230,246,246,0.6); //#e6f6f6;
    }

    th[id$='7'] {
    background: rgba(231,247,247,0.6); //#e7f7f7;
    }

    th[id$='8'] {
    background: rgba(232,248,248,0.6); //#e2f2f2;
    }

    th[id$='9'] {
    background: rgba(233,249,249,0.6); //#e9f9f9;
    }

    td[id$='0'] {
    background: rgba(240,240,240,0.3); //#f0f0f0;
    text-shadow:-1px 1px 1px #ff2d90;
    }

    td[id$='1'] {
    background: rgba(241,241,241,0.3); //#f1f1f1;
    text-shadow:-1px 1px 1px #ff2d91;
    float: bottom;
    }

    td[id$='2'] {
    background: rgba(242,242,242,0.3); //#f2f2f2;
    text-shadow:-1px 1px 1px #ff2d92;
    }

    td[id$='3'] {
    background: rgba(243,243,243,0.3); //#f3f3f3;
    text-shadow:-1px 1px 1px #ff2d93;
    }

    td[id$='4'] {
    background: rgba(244,244,244,0.3); //#f4f4f4;
    text-shadow:-1px 1px 1px #ff2d94;
    }

    td[id$='5'] {
    background: rgba(245,245,245,0.3); //#f5f5f5;
    text-shadow:-1px 1px 1px #ff2d95;
    }

    td[id$='6'] {
    background: rgba(246,246,246,0.3); //#f6f6f6;
    text-shadow:-1px 1px 1px #ff2d96;
    }

    td[id$='7'] {
    background: rgba(247,247,247,0.3); //#f7f7f7;
    text-shadow:-1px 1px 1px #ff2d97;
    }

    td[id$='8'] {
    background: rgba(248,248,248,0.3); //#f8f8f8;
    text-shadow:-1px 1px 1px #ff2d98;
    }

    td[id$='9'] {
    background: rgba(249,249,249,0.3); //#f9f9f9;
    text-shadow:-1px 1px 1px #ff2d99;
    }

    table tbody tr:first-child {
    background: transparent; //#f6f6e6;
    }
    </style>

    “; ?>
    … and then …
  • whenever new cell content happens padding-top adding CSS Javascript DOM nuanced display logic via …
    <?php echo ”

    function paddingtopit() {
    var maxtwo=0, thistwo=0;
    var thhs=[], tdhs=[], it=0;
    var thdids=[];
    //trthtd1
    //trtdtd1
    var tds=document.getElementsByTagName('td');
    for (it=0; it<tds.length; it++) {
    if (('' + tds[it].id).indexOf('trtdtd') != -1) {
    if (('' + tds[it].style.paddingTop).replace(/^null/g,'').replace(/^undefined/g,'').trim() != '') {
    tds[it].style.paddingTop='0px';
    }
    }
    }
    for (it=0; it<tds.length; it++) {
    if (('' + tds[it].id).indexOf('trtdtd') != -1) {
    tdhs.push(eval('' + tds[it].getBoundingClientRect().height));
    thdids.push('' + tds[it].id);
    }
    }
    var ths=document.getElementsByTagName('th');
    for (it=0; it<ths.length; it++) {
    if (('' + ths[it].id).indexOf('trthtd') != -1) {
    thhs.push(eval('' + ths[it].getBoundingClientRect().height));
    thistwo=eval(thhs[it] + tdhs[it]);
    if (thistwo > maxtwo) { maxtwo=thistwo; }
    }
    }
    for (it=0; it<tdhs.length; it++) {
    thistwo=eval(thhs[it] + tdhs[it]);
    if (thistwo < maxtwo) {
    document.getElementById(thdids[it]).style.paddingTop='' + eval(maxtwo - thistwo) + 'px';
    }
    }
    }

    “; ?>
    … so that …
  • cartoons present with “speech bubble” wording aligned to the top in our “cells” (ie. th contenteditable=true editable wording on top of td horizontal flip (double click) and/or vertical flop (right click) editable lower part) with those characters aligned to the bottom

… in our changed “third draft” Cartoon creation and email sharing capable PHP web application you can also try below.


Previous relevant Python Cowsay API Primer Tutorial is shown below.

Python Cowsay API Primer Tutorial

Python Cowsay API Primer Tutorial

We discovered an interesting Open Source Python API / Command-line tool called cowsay which we installed up at our AlmaLinux web server via …


pip install cowsay

… with an integration purpose in mind, so thanks. Before many readers’ time indeed, but some may remember those cute banner printouts that told you who owned the next printout on a spooling “crude graphics” printout in the late 70’s … well cowsay encapsulates those heady days (and who can forget punch cards)?! Before integration, though, we want to test it via a new PHP supervisor on exec method Linux command line interfacings to cowsay.

So we started, with this “first draft” getting places and then this “second draft” with a little more sophistication to leave the day with this interfacer

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

Posted in eLearning, Operating System, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , | Leave a comment

Bluetooth Spotify Auto Stop Start Primer Tutorial

Bluetooth Spotify Auto Stop Start Primer Tutorial

Bluetooth Spotify Auto Stop Start Primer Tutorial

We’re amazed by an arrangement involving …

  • iPhone … with …
  • Spotify … in a subscription involving no advertisements …
  • Bluetooth … speakers in a …
  • Volvo … car

… currently (ie. you can easily stuff it up, but if in it’s best mode) whereby …

  • just getting out of the car is enough to stop the music we’ve been playing … and …
  • just getting back in to the car it restarts the music from where you left it if you have not been playing through the iPhone speakers in the meantime

handsfree!

Oops! It annoys some people …

Bluetooth Spotify Auto Stop Start Volvo

If this was interesting you may be interested in this too.

Posted in eLearning, Hardware, Networking, Tutorials | Tagged , , , , , , , , , , , , | Leave a comment