Recherche avancée

Médias (91)

Autres articles (111)

  • Script d’installation automatique de MediaSPIP

    25 avril 2011, par

    Afin de palier aux difficultés d’installation dues principalement aux dépendances logicielles coté serveur, un script d’installation "tout en un" en bash a été créé afin de faciliter cette étape sur un serveur doté d’une distribution Linux compatible.
    Vous devez bénéficier d’un accès SSH à votre serveur et d’un compte "root" afin de l’utiliser, ce qui permettra d’installer les dépendances. Contactez votre hébergeur si vous ne disposez pas de cela.
    La documentation de l’utilisation du script d’installation (...)

  • Ajouter des informations spécifiques aux utilisateurs et autres modifications de comportement liées aux auteurs

    12 avril 2011, par

    La manière la plus simple d’ajouter des informations aux auteurs est d’installer le plugin Inscription3. Il permet également de modifier certains comportements liés aux utilisateurs (référez-vous à sa documentation pour plus d’informations).
    Il est également possible d’ajouter des champs aux auteurs en installant les plugins champs extras 2 et Interface pour champs extras.

  • Librairies et binaires spécifiques au traitement vidéo et sonore

    31 janvier 2010, par

    Les logiciels et librairies suivantes sont utilisées par SPIPmotion d’une manière ou d’une autre.
    Binaires obligatoires FFMpeg : encodeur principal, permet de transcoder presque tous les types de fichiers vidéo et sonores dans les formats lisibles sur Internet. CF ce tutoriel pour son installation ; Oggz-tools : outils d’inspection de fichiers ogg ; Mediainfo : récupération d’informations depuis la plupart des formats vidéos et sonores ;
    Binaires complémentaires et facultatifs flvtool2 : (...)

Sur d’autres sites (8045)

  • How to Track Website Visitors : Benefits, Tools and FAQs

    31 août 2023, par Erin — Analytics Tips, Marketing

    Businesses spend a ton of time, money and effort into creating websites that are not only helpful and captivating, but also highly effective at converting visitors. They’ll create content, revise designs, add new pages and change forms, all in the hope of getting visitors to stay on the site and convert into leads or customers.

    When you track website visitors, you can see which of your efforts are moving the needle. While many people are familiar with pageviews as a metric, website visitor tracking can be much more in-depth and insightful.

    In this article, we’ll cover how website visitor tracking works, what you can track, and how this information can improve sales and marketing results. We’ll also explain global privacy concerns and how businesses can choose the right tracking software. 

    What is website visitor tracking ? 

    Website visitor tracking uses software and applications to track and analyse how visitors interact with your website. It’s a vital tool to help businesses understand whether their website design and content are having the desired effect.

    Website with user profile

    Website visitor tracking includes very broad, non-specific data, like how many times visitors have come to your site. But it can also get very specific, with personal information about the user and even recordings of their visit to your site. Site visits, which may include visiting several different pages of the same site, are often referred to as “sessions.”

    Although Google Analytics is the most widely used website visitor tracking software, it isn’t the most comprehensive or powerful. Companies that want a more in-depth understanding of their website may need to consider running a more precise tool alongside Google Analytics, like Matomo.

    As we’ll cover later, website tracking has many important business applications, but it also poses privacy and security concerns, causing some states and countries to impose strict regulations. Privacy laws and your company’s values should also impact what web analytics tool you choose.

    How website tracking works

    Website tracking starts with the collection of data as users interact with the website. Tracking technologies like cookies, JavaScript and pixels are embedded into web pages. These technologies then gather data about user behaviour, session details and user actions, such as pageviews, clicks, form submissions and more.

    More advanced tracking systems assign unique identifiers (such as cookies or visitor IDs) to individual users. This enables tracking of user journeys across multiple sessions and pages. These detailed journeys can often tell a different story and provide different insights than aggregated numbers do. 

    All this collected data is transmitted from the user’s browser to a centralised tracking system, which can be a third-party web analytics tool or a self-hosted solution. The collected data is stored in databases and processed to generate meaningful insights. This process involves organising the data, aggregating metrics, and creating reports.

    Analytics tools process the collected data to generate reports and visualisations that provide insights into user behaviour. Metrics such as pageviews, bounce rates, conversion rates and user paths are analysed. Good web analytics tools are able to present these insights in a user-friendly way. Analysts and marketing professionals then use this knowledge to make informed decisions to improve the user experience (UX).

    Advanced tracking systems allow data segmentation and filtering based on various criteria, such as user demographics, traffic sources, devices and more. This enables deeper analysis of specific user groups. For example, you might find that your conversion rate is much lower when your website is viewed on a mobile device. You can then dig deeper into that segment of data to find out why and experiment with changes that might increase mobile conversions.

    3 types of website tracking and their benefits

    There are three main categories of website tracking, and they each provide different information that can be used by sales, marketing, engineering and others. Here, we cover those three types and how businesses use them to understand customers and create better experiences.

    Website analytics 

    Website analytics is all about understanding the traffic your website receives. This type of tracking allows you to learn how the website performs based on pageviews, real-time traffic, bounce rate and conversions. 

    For example, you would use website analytics to determine how effectively your homepage drives people toward a product or pricing page. You can use pageviews and previous page statistics to learn how many people who land on your homepage read your blog posts. From there, you could use web analytics to determine the conversion rate of the call to action at the end of each article.

    Analytics, user behaviour and information

    User behaviour

    While website analytics focuses on the website’s performance, user behaviour tracking is about monitoring and quantifying user behaviour. One of the most obvious aspects of user behaviour is what they click on, but there are many other actions you can track. 

    The time a user spends on a page can help you determine whether the content on the page is engaging. Some tracking tools can also measure how far down the page a user scrolls, which reveals whether some content is even being seen. 

    Session recordings are another popular tool for analysing user behaviour. They not only show concrete actions, like clicks, but can also show how the user moves throughout the page. Where do they stop ? What do they scroll right past ? This is one example of how user behaviour data can be quantitative or qualitative.

    Visitor information

    Tracking can also include gathering or uncovering information about visitors to your site. This might include demographic information, such as language and location, or details like what device a website visitor is using and on which browser they view your website. 

    This type of data helps your web and marketing teams make better decisions about how to design and format the site. If you know, for example, that the website for your business-to-business (B2B) software is overwhelmingly viewed on desktop computers, that will affect how you structure your pages and choose images. 

    Similarly, if visitor information tells you that you have a significant audience in France, your marketing team might develop new content to appeal to those potential customers.

    Use website visitor tracking to improve marketing, sales and UX 

    Website visitor tracking has various applications for different parts of your business, from marketing to sales and much more. When you understand the impact tracking has on different teams, you can better evaluate your company’s needs and build buy-in among stakeholders.

    Marketing

    At many companies, the marketing team owns and determines what kind of content is on your website. From landing pages to blog posts to the navigation bar, you want to create an experience that drives people toward making a purchase. When marketers can track website visitors, they can get a real look at how visitors respond to and engage with their marketing efforts. Pageviews, conversion rates and time spent on pages help them better understand what your customers care about and what messaging resonates.

    But web analytics can even help marketing teams better understand how their external marketing campaigns are performing. Tracking tools like Matomo reveal your most important traffic sources. The term “traffic source” refers to the content or web property from which someone arrives at your site. 

    For instance, you might notice that an older page got a big boost in traffic this month. You can then check the traffic sources, where you find that an influential LinkedIn user posted a link to the page. This presents an opportunity to adjust the influencer or social media aspects of your marketing strategy.

    Beyond traffic sources, Matomo can provide a visual user journey (also known as User Flow), showing which pages visitors tend to view in a session and even in what order they progress. This gives you a bird’s-eye view of the customer journey.

    Sales

    Just like your marketing team, your sales team can benefit from tracking and analysing website visitor information. Data about user behaviour and visitor demographics helps sales representatives better understand the people they’re talking to. Segmented visitor tracking data can even provide clues as to how to appeal to different buyer personas.

    Sales leadership can use web analytics to gauge interest over time, tie visitors to revenue and develop more accurate sales forecasts and goals. 

    And it’s not just aggregated website tracking data that your sales team can use to better serve customers. They can also use insights about an individual visitor to tailor their approach. Matomo’s Visits Log report and Visitor Profiles allow you to see which pages a prospect has viewed. This tells your sales team which products and features the prospect is most interested in, leading to more relevant interactions and more effective sales efforts.

    User experience and web development

    The way users interact with and experience your website has a big impact on their impression of your brand and, ultimately, whether they become customers. While marketing often controls much of a website’s content, the backend and technical operation of the site usually falls to a web development or engineering team. Website analytics and tracking inform their work, too.

    Along with data about website traffic and conversion rates, web development teams often monitor bounce rates (the percentage of people who leave your website entirely after landing on a page) and page load time (the time it takes for an individual web page to load for a user). Besides the fact that slow loading times inconvenience visitors, they can also negatively affect your search engine optimization (SEO).

    Along with session recordings, user experience teams and web developers may use heatmaps to find out what parts of a page draw a visitor’s attention and where they are most likely to convert or take some other action. They can then use these insights to make a web page more intuitive and useful.

    Visitor tracking and privacy regulations 

    There are different data privacy standards in other parts of the world, which are designed to ensure that businesses collect and use consumer data ethically. The most-discussed of these privacy standards is the General Data Protection Regulation (GDPR), which was instituted by the European Union (EU) but affects businesses worldwide. However, it’s important to note that individual countries or states can have different privacy laws.

    Many privacy laws govern how websites can use cookies to track visitors. With a user’s consent, cookies can help websites identify and remember visitors. However, many web visitors will reject cookie consent banners. When this happens, analysts and marketers can’t collect information from these visitors and have to work with incomplete tracking data. Incomplete data leads to poor decision-making. What’s more, cookie consent banners can create a poor user experience and often annoy web visitors.

    With Matomo’s industry-leading measures to protect user privacy, France’s data protection agency (CNIL) has confirmed that Matomo is exempt from tracking consent in France. Matomo users have peace of mind knowing they can uphold the GDPR and collect data without needing to collect and track cookie consent. Only in Germany and the UK are cookie consent banners still required.

    Choosing user tracking software

    The benefits and value of tracking website visitors are enormous, but not all tracking software is equal. Different tools have different core functionalities. For instance, some focus on user behaviour over traditional web analytics. Others offer detailed website performance data but offer little in the way of visitor information. It’s a good idea to start by identifying your company’s most important tracking goals.

    Along with core features, look for useful tools to experiment with and optimise your website with. For example, Matomo enables A/B testing while many other tools do not.

    Along with users of your website, you also need to think about the employees who will be using the tracking software. The interface can have a big impact on the value you get from a tool. Matomo’s session recording functionality, for example, not only provides you with video but with a colour-coded timeline identifying important user actions.

    Privacy standards and compliance should also be a part of the conversation. Different tools use different tracking methods, impacting accuracy and security and can even cause legal trouble. You should consider which data privacy laws you are subject to, as well as the privacy expectations of your users.

    Cloud-based tool and on-premises software

    Some industries have especially high data security standards. Government and healthcare organisations, for example, may require visitor tracking software that is hosted on their premises. While there are many purely cloud-based software-as-a-service (SaaS) tracking tools, Matomo is available both On-Premise (also known as self-hosted) and in the Cloud.

    Frequently asked questions

    Here are answers to some of people’s most common questions about tracking website visitors.

    Can you track who visited your website ?

    In most cases, tracking your website’s traffic is possible. Still, the extent of the tracking depends on the visitor-tracking technology you use and the privacy settings and precautions the visitor uses. For example, some technologies can pinpoint users by IP address. In other cases, you may only have access to anonymized data.

    Is it legal to track someone’s IP address ?

    It is legal for websites and businesses to track someone’s IP address in the sense that they can identify that someone from the same IP address is visiting a page repeatedly. Under the General Data Protection Regulation (GDPR), IP addresses are considered personally identifiable information (PII). The GDPR mandates that websites only log and store a user’s IP address with the user’s consent.

    How do you find where visitors are clicking the most ?

    Heatmap tools are among the most common tools for learning where visitors click the most on your website. Heatmaps use colour-coding to show what parts of a web page users either click on or hover over the most.

    Unique tracking URLs are another way to determine what part of your website gets the most clicks. For example, if you have three links on a page that all go to the same destination, you can use tracking links to determine how many clicks each link generates.

    Matomo also offers a Tag Manager within the platform that lets you manage and unify all your tracking and marketing tags to find out where visitors are clicking.

    What is the best tool for website visitor tracking ?

    Like most tools, the best website visitor tracking tool depends on your needs. Each tool offers different functionalities, user interfaces and different levels of accuracy and privacy. Matomo is a good choice for companies that value privacy, compliance and accuracy.

    Tracking for powerful insights and better performance

    Tracking website visitors is now a well-ingrained part of business operations. From sales reps seeking to understand their leads to marketers honing their ad spend, tracking helps teams do their jobs better.

    Take the time to consider what you want to learn from website tracking and let those priorities guide your choice of visitor tracking software. Whatever your industry or needs, user privacy and compliance must be a priority.

    Find out how much detail and insight Matomo can give you with our free 21-day trial — no credit card required.

  • Things I Have Learned About Emscripten

    1er septembre 2015, par Multimedia Mike — Cirrus Retro

    3 years ago, I released my Game Music Appreciation project, a website with a ludicrously uninspired title which allowed users a relatively frictionless method to experience a range of specialized music files related to old video games. However, the site required use of a special Chrome plugin. Ever since that initial release, my #1 most requested feature has been for a pure JavaScript version of the music player.

    “Impossible !” I exclaimed. “There’s no way JS could ever run fast enough to run these CPU emulators and audio synthesizers in real time, and allow for the visualization that I demand !” Well, I’m pleased to report that I have proved me wrong. I recently quietly launched a new site with what I hope is a catchier title, meant to evoke a cloud-based retro-music-as-a-service product : Cirrus Retro. Right now, it’s basically the same as the old site, but without the wonky Chrome-specific technology.

    Along the way, I’ve learned a few things about using Emscripten that I thought might be useful to share with other people who wish to embark on a similar journey. This is geared more towards someone who has a stronger low-level background (such as C/C++) vs. high-level (like JavaScript).

    General Goals
    Do you want to cross-compile an entire desktop application, one that relies on an extensive GUI toolkit ? That might be difficult (though I believe there is a path for porting qt code directly with Emscripten). Your better wager might be to abstract out the core logic and processes of the program and then create a new web UI to access them.

    Do you want to compile a game that basically just paints stuff to a 2D canvas ? You’re in luck ! Emscripten has a porting path for SDL. Make a version of your C/C++ software that targets SDL (generally not a tall order) and then compile that with Emscripten.

    Do you just want to cross-compile some functionality that lives in a library ? That’s what I’ve done with the Cirrus Retro project. For this, plan to compile the library into a JS file that exports some public functions that other, higher-level, native JS (i.e., JS written by a human and not a computer) will invoke.

    Memory Levels
    When porting C/C++ software to JavaScript using Emscripten, you have to think on 2 different levels. Or perhaps you need to force JavaScript into a low level C lens, especially if you want to write native JS code that will interact with Emscripten-compiled code. This often means somehow allocating chunks of memory via JS and passing them to the Emscripten-compiled functions. And you wouldn’t believe the type of gymnastics you need to execute to get native JS and Emscripten-compiled JS to cooperate.

    “Emscripten : Pointers and Pointers” is the best (and, really, ONLY) explanation I could find for understanding the basic mechanics of this process, at least when I started this journey. However, there’s a mistake in the explanation that left me confused for a little while, and I’m at a loss to contact the author (doesn’t anyone post a simple email address anymore ?).

    Per the best of my understanding, Emscripten allocates a large JS array and calls that the memory space that the compiled C/C++ code is allowed to operate in. A pointer in C/C++ code will just be an index into that mighty array. Really, that’s not too far off from how a low-level program process is supposed to view memory– as a flat array.

    Eventually, I just learned to cargo-cult my way through the memory allocation process. Here’s the JS code for allocating an Emscripten-compatible byte buffer, taken from my test harness (more on that later) :

    var musicBuffer = fs.readFileSync(testSpec[’filename’]) ;
    var musicBufferBytes = new Uint8Array(musicBuffer) ;
    var bytesMalloc = player._malloc(musicBufferBytes.length) ;
    var bytes = new Uint8Array(player.HEAPU8.buffer, bytesMalloc, musicBufferBytes.length) ;
    bytes.set(new Uint8Array(musicBufferBytes.buffer)) ;
    

    So, read the array of bytes from some input source, create a Uint8Array from the bytes, use the Emscripten _malloc() function to allocate enough bytes from the Emscripten memory array for the input bytes, then create a new array… then copy the bytes…

    You know what ? It’s late and I can’t remember how it works exactly, but it does. It has been a few months since I touched that code (been fighting with front-end website tech since then). You write that memory allocation code enough times and it begins to make sense, and then you hope you don’t have to write it too many more times.

    Multithreading
    You can’t port multithreaded code to JS via Emscripten. JavaScript has no notion of threads ! If you don’t understand the computer science behind this limitation, a more thorough explanation is beyond the scope of this post. But trust me, I’ve thought about it a lot. In fact, the official Emscripten literature states that you should be able to port most any C/C++ code as long as 1) none of the code is proprietary (i.e., all the raw source is available) ; and 2) there are no threads.

    Yes, I read about the experimental pthreads support added to Emscripten recently. Don’t get too excited ; that won’t be ready and widespread for a long time to come as it relies on a new browser API. In the meantime, figure out how to make your multithreaded C/C++ code run in a single thread if you want it to run in a browser.

    Printing Facility
    Eventually, getting software to work boils down to debugging, and the most primitive tool in many a programmer’s toolbox is the humble print statement. A print statement allows you to inspect a piece of a program’s state at key junctures. Eventually, when you try to cross-compile C/C++ code to JS using Emscripten, something is not going to work correctly in the generated JS “object code” and you need to understand what. You’ll be pleading for a method of just inspecting one variable deep in the original C/C++ code.

    I came up with this simple printf-workalike called emprintf() :

    #ifndef EMPRINTF_H
    #define EMPRINTF_H
    

    #include <stdio .h>
    #include <stdarg .h>
    #include <emscripten .h>

    #define MAX_MSG_LEN 1000

    /* NOTE : Don’t pass format strings that contain single quote (’) or newline
    * characters. */
    static void emprintf(const char *format, ...)

    char msg[MAX_MSG_LEN] ;
    char consoleMsg[MAX_MSG_LEN + 16] ;
    va_list args ;

    /* create the string */
    va_start(args, format) ;
    vsnprintf(msg, MAX_MSG_LEN, format, args) ;
    va_end(args) ;

    /* wrap the string in a console.log(’’) statement */
    snprintf(consoleMsg, MAX_MSG_LEN + 16, "console.log(’%s’)", msg) ;

    /* send the final string to the JavaScript console */
    emscripten_run_script(consoleMsg) ;

    #endif /* EMPRINTF_H */

    Put it in a file called “emprint.h”. Include it into any C/C++ file where you need debugging visibility, use emprintf() as a replacement for printf() and the output will magically show up on the browser’s JavaScript debug console. Heed the comments and don’t put any single quotes or newlines in strings, and keep it under 1000 characters. I didn’t say it was perfect, but it has helped me a lot in my Emscripten adventures.

    Optimization Levels
    Remember to turn on optimization when compiling. I have empirically found that optimizing for size (-Os) leads to the best performance all around, in addition to having the smallest size. Just be sure to specify some optimization level. If you don’t, the default is -O0 which offers horrible performance when running in JS.

    Static Compression For HTTP Delivery
    JavaScript code compresses pretty efficiently, even after it has been optimized for size using -Os. I routinely see compression ratios between 3.5:1 and 5:1 using gzip.

    Web servers in this day and age are supposed to be smart enough to detect when a requesting web browser can accept gzip-compressed data and do the compression on the fly. They’re even supposed to be smart enough to cache compressed output so the same content is not recompressed for each request. I would have to set up a series of tests to establish whether either of the foregoing assertions are correct and I can’t be bothered. Instead, I took it into my own hands. The trick is to pre-compress the JS files and then instruct the webserver to serve these files with a ‘Content-Type’ of ‘application/javascript’ and a ‘Content-Encoding’ of ‘gzip’.

    1. Compress your large Emscripten-build JS files with ‘gzip’ : ‘gzip compiled-code.js’
    2. Rename them from extension .js.gz to .jsgz
    3. Tell the webserver to deliver .jsgz files with the correct Content-Type and Content-Encoding headers

    To do that last step with Apache, specify these lines :

    AddType application/javascript jsgz
    AddEncoding gzip jsgz
    

    They belong in either a directory’s .htaccess file or in the sitewide configuration (/etc/apache2/mods-available/mime.conf works on my setup).

    Build System and Build Time Optimization
    Oh goodie, build systems ! I had a very specific manner in which I wanted to build my JS modules using Emscripten. Can I possibly coerce any of the many popular build systems to do this ? It has been a few months since I worked on this problem specifically but I seem to recall that the build systems I tried to used would freak out at the prospect of compiling stuff to a final binary target of .js.

    I had high hopes for Bazel, which Google released while I was developing Cirrus Retro. Surely, this is software that has been battle-tested in the harshest conditions of one of the most prominent software-developing companies in the world, needing to take into account the most bizarre corner cases and still build efficiently and correctly every time. And I have little doubt that it fulfills the order. Similarly, I’m confident that Google also has a team of no fewer than 100 or so people dedicated to developing and supporting the project within the organization. When you only have, at best, 1-2 hours per night to work on projects like this, you prefer not to fight with such cutting edge technology and after losing 2 or 3 nights trying to make a go of Bazel, I eventually put it aside.

    I also tried to use Autotools. It failed horribly for me, mostly for my own carelessness and lack of early-project source control.

    After that, it was strictly vanilla makefiles with no real dependency management. But you know what helps in these cases ? ccache ! Or at least, it would if it didn’t fail with Emscripten.

    Quick tip : ccache has trouble with LLVM unless you set the CCACHE_CPP2 environment variable (e.g. : “export CCACHE_CPP2=1”). I don’t remember the specifics, but it magically fixes things. Then, the lazy build process becomes “make clean && make”.

    Testing
    If you have never used Node.js, testing Emscripten-compiled JS code might be a good opportunity to start. I was able to use Node.js to great effect for testing the individually-compiled music player modules, wiring up a series of invocations using Python for a broader test suite (wouldn’t want to go too deep down the JS rabbit hole, after all).

    Be advised that Node.js doesn’t enjoy the same kind of JIT optimizations that the browser engines leverage. Thus, in the case of time critical code like, say, an audio synthesis library, the code might not run in real time. But as long as it produces the correct bitwise waveform, that’s good enough for continuous integration.

    Also, if you have largely been a low-level programmer for your whole career and are generally unfamiliar with the world of single-threaded, event-driven, callback-oriented programming, you might be in for a bit of a shock. When I wanted to learn how to read the contents of a file in Node.js, this is the first tutorial I found on the matter. I thought the code presented was a parody of bad coding style :

    var fs = require("fs") ;
    var fileName = "foo.txt" ;
    

    fs.exists(fileName, function(exists)
    if (exists)
    fs.stat(fileName, function(error, stats)
    fs.open(fileName, "r", function(error, fd)
    var buffer = new Buffer(stats.size) ;

    fs.read(fd, buffer, 0, buffer.length, null, function(error, bytesRead, buffer)
    var data = buffer.toString("utf8", 0, buffer.length) ;

    console.log(data) ;
    fs.close(fd) ;
    ) ;
    ) ;
    ) ;
    ) ;

    Apparently, this kind of thing doesn’t raise an eyebrow in the JS world.

    Now, I understand and respect the JS programming model. But this was seriously frustrating when I first encountered it because a simple script like the one I was trying to write just has an ordered list of tasks to complete. When it asks for bytes from a file, it really has nothing better to do than to wait for the answer.

    Thankfully, it turns out that Node’s fs module includes synchronous versions of the various file access functions. So it’s all good.

    Conclusion
    I’m sure I missed or underexplained some things. But if other brave souls are interested in dipping their toes in the waters of Emscripten, I hope these tips will come in handy.

    The post Things I Have Learned About Emscripten first appeared on Breaking Eggs And Making Omelettes.

  • Things I Have Learned About Emscripten

    1er septembre 2015, par Multimedia Mike — Cirrus Retro

    3 years ago, I released my Game Music Appreciation project, a website with a ludicrously uninspired title which allowed users a relatively frictionless method to experience a range of specialized music files related to old video games. However, the site required use of a special Chrome plugin. Ever since that initial release, my #1 most requested feature has been for a pure JavaScript version of the music player.

    “Impossible !” I exclaimed. “There’s no way JS could ever run fast enough to run these CPU emulators and audio synthesizers in real time, and allow for the visualization that I demand !” Well, I’m pleased to report that I have proved me wrong. I recently quietly launched a new site with what I hope is a catchier title, meant to evoke a cloud-based retro-music-as-a-service product : Cirrus Retro. Right now, it’s basically the same as the old site, but without the wonky Chrome-specific technology.

    Along the way, I’ve learned a few things about using Emscripten that I thought might be useful to share with other people who wish to embark on a similar journey. This is geared more towards someone who has a stronger low-level background (such as C/C++) vs. high-level (like JavaScript).

    General Goals
    Do you want to cross-compile an entire desktop application, one that relies on an extensive GUI toolkit ? That might be difficult (though I believe there is a path for porting qt code directly with Emscripten). Your better wager might be to abstract out the core logic and processes of the program and then create a new web UI to access them.

    Do you want to compile a game that basically just paints stuff to a 2D canvas ? You’re in luck ! Emscripten has a porting path for SDL. Make a version of your C/C++ software that targets SDL (generally not a tall order) and then compile that with Emscripten.

    Do you just want to cross-compile some functionality that lives in a library ? That’s what I’ve done with the Cirrus Retro project. For this, plan to compile the library into a JS file that exports some public functions that other, higher-level, native JS (i.e., JS written by a human and not a computer) will invoke.

    Memory Levels
    When porting C/C++ software to JavaScript using Emscripten, you have to think on 2 different levels. Or perhaps you need to force JavaScript into a low level C lens, especially if you want to write native JS code that will interact with Emscripten-compiled code. This often means somehow allocating chunks of memory via JS and passing them to the Emscripten-compiled functions. And you wouldn’t believe the type of gymnastics you need to execute to get native JS and Emscripten-compiled JS to cooperate.

    “Emscripten : Pointers and Pointers” is the best (and, really, ONLY) explanation I could find for understanding the basic mechanics of this process, at least when I started this journey. However, there’s a mistake in the explanation that left me confused for a little while, and I’m at a loss to contact the author (doesn’t anyone post a simple email address anymore ?).

    Per the best of my understanding, Emscripten allocates a large JS array and calls that the memory space that the compiled C/C++ code is allowed to operate in. A pointer in C/C++ code will just be an index into that mighty array. Really, that’s not too far off from how a low-level program process is supposed to view memory– as a flat array.

    Eventually, I just learned to cargo-cult my way through the memory allocation process. Here’s the JS code for allocating an Emscripten-compatible byte buffer, taken from my test harness (more on that later) :

    var musicBuffer = fs.readFileSync(testSpec[’filename’]) ;
    var musicBufferBytes = new Uint8Array(musicBuffer) ;
    var bytesMalloc = player._malloc(musicBufferBytes.length) ;
    var bytes = new Uint8Array(player.HEAPU8.buffer, bytesMalloc, musicBufferBytes.length) ;
    bytes.set(new Uint8Array(musicBufferBytes.buffer)) ;
    

    So, read the array of bytes from some input source, create a Uint8Array from the bytes, use the Emscripten _malloc() function to allocate enough bytes from the Emscripten memory array for the input bytes, then create a new array… then copy the bytes…

    You know what ? It’s late and I can’t remember how it works exactly, but it does. It has been a few months since I touched that code (been fighting with front-end website tech since then). You write that memory allocation code enough times and it begins to make sense, and then you hope you don’t have to write it too many more times.

    Multithreading
    You can’t port multithreaded code to JS via Emscripten. JavaScript has no notion of threads ! If you don’t understand the computer science behind this limitation, a more thorough explanation is beyond the scope of this post. But trust me, I’ve thought about it a lot. In fact, the official Emscripten literature states that you should be able to port most any C/C++ code as long as 1) none of the code is proprietary (i.e., all the raw source is available) ; and 2) there are no threads.

    Yes, I read about the experimental pthreads support added to Emscripten recently. Don’t get too excited ; that won’t be ready and widespread for a long time to come as it relies on a new browser API. In the meantime, figure out how to make your multithreaded C/C++ code run in a single thread if you want it to run in a browser.

    Printing Facility
    Eventually, getting software to work boils down to debugging, and the most primitive tool in many a programmer’s toolbox is the humble print statement. A print statement allows you to inspect a piece of a program’s state at key junctures. Eventually, when you try to cross-compile C/C++ code to JS using Emscripten, something is not going to work correctly in the generated JS “object code” and you need to understand what. You’ll be pleading for a method of just inspecting one variable deep in the original C/C++ code.

    I came up with this simple printf-workalike called emprintf() :

    #ifndef EMPRINTF_H
    #define EMPRINTF_H
    

    #include <stdio .h>
    #include <stdarg .h>
    #include <emscripten .h>

    #define MAX_MSG_LEN 1000

    /* NOTE : Don’t pass format strings that contain single quote (’) or newline
    * characters. */
    static void emprintf(const char *format, ...)

    char msg[MAX_MSG_LEN] ;
    char consoleMsg[MAX_MSG_LEN + 16] ;
    va_list args ;

    /* create the string */
    va_start(args, format) ;
    vsnprintf(msg, MAX_MSG_LEN, format, args) ;
    va_end(args) ;

    /* wrap the string in a console.log(’’) statement */
    snprintf(consoleMsg, MAX_MSG_LEN + 16, "console.log(’%s’)", msg) ;

    /* send the final string to the JavaScript console */
    emscripten_run_script(consoleMsg) ;

    #endif /* EMPRINTF_H */

    Put it in a file called “emprint.h”. Include it into any C/C++ file where you need debugging visibility, use emprintf() as a replacement for printf() and the output will magically show up on the browser’s JavaScript debug console. Heed the comments and don’t put any single quotes or newlines in strings, and keep it under 1000 characters. I didn’t say it was perfect, but it has helped me a lot in my Emscripten adventures.

    Optimization Levels
    Remember to turn on optimization when compiling. I have empirically found that optimizing for size (-Os) leads to the best performance all around, in addition to having the smallest size. Just be sure to specify some optimization level. If you don’t, the default is -O0 which offers horrible performance when running in JS.

    Static Compression For HTTP Delivery
    JavaScript code compresses pretty efficiently, even after it has been optimized for size using -Os. I routinely see compression ratios between 3.5:1 and 5:1 using gzip.

    Web servers in this day and age are supposed to be smart enough to detect when a requesting web browser can accept gzip-compressed data and do the compression on the fly. They’re even supposed to be smart enough to cache compressed output so the same content is not recompressed for each request. I would have to set up a series of tests to establish whether either of the foregoing assertions are correct and I can’t be bothered. Instead, I took it into my own hands. The trick is to pre-compress the JS files and then instruct the webserver to serve these files with a ‘Content-Type’ of ‘application/javascript’ and a ‘Content-Encoding’ of ‘gzip’.

    1. Compress your large Emscripten-build JS files with ‘gzip’ : ‘gzip compiled-code.js’
    2. Rename them from extension .js.gz to .jsgz
    3. Tell the webserver to deliver .jsgz files with the correct Content-Type and Content-Encoding headers

    To do that last step with Apache, specify these lines :

    AddType application/javascript jsgz
    AddEncoding gzip jsgz
    

    They belong in either a directory’s .htaccess file or in the sitewide configuration (/etc/apache2/mods-available/mime.conf works on my setup).

    Build System and Build Time Optimization
    Oh goodie, build systems ! I had a very specific manner in which I wanted to build my JS modules using Emscripten. Can I possibly coerce any of the many popular build systems to do this ? It has been a few months since I worked on this problem specifically but I seem to recall that the build systems I tried to used would freak out at the prospect of compiling stuff to a final binary target of .js.

    I had high hopes for Bazel, which Google released while I was developing Cirrus Retro. Surely, this is software that has been battle-tested in the harshest conditions of one of the most prominent software-developing companies in the world, needing to take into account the most bizarre corner cases and still build efficiently and correctly every time. And I have little doubt that it fulfills the order. Similarly, I’m confident that Google also has a team of no fewer than 100 or so people dedicated to developing and supporting the project within the organization. When you only have, at best, 1-2 hours per night to work on projects like this, you prefer not to fight with such cutting edge technology and after losing 2 or 3 nights trying to make a go of Bazel, I eventually put it aside.

    I also tried to use Autotools. It failed horribly for me, mostly for my own carelessness and lack of early-project source control.

    After that, it was strictly vanilla makefiles with no real dependency management. But you know what helps in these cases ? ccache ! Or at least, it would if it didn’t fail with Emscripten.

    Quick tip : ccache has trouble with LLVM unless you set the CCACHE_CPP2 environment variable (e.g. : “export CCACHE_CPP2=1”). I don’t remember the specifics, but it magically fixes things. Then, the lazy build process becomes “make clean && make”.

    Testing
    If you have never used Node.js, testing Emscripten-compiled JS code might be a good opportunity to start. I was able to use Node.js to great effect for testing the individually-compiled music player modules, wiring up a series of invocations using Python for a broader test suite (wouldn’t want to go too deep down the JS rabbit hole, after all).

    Be advised that Node.js doesn’t enjoy the same kind of JIT optimizations that the browser engines leverage. Thus, in the case of time critical code like, say, an audio synthesis library, the code might not run in real time. But as long as it produces the correct bitwise waveform, that’s good enough for continuous integration.

    Also, if you have largely been a low-level programmer for your whole career and are generally unfamiliar with the world of single-threaded, event-driven, callback-oriented programming, you might be in for a bit of a shock. When I wanted to learn how to read the contents of a file in Node.js, this is the first tutorial I found on the matter. I thought the code presented was a parody of bad coding style :

    var fs = require("fs") ;
    var fileName = "foo.txt" ;
    

    fs.exists(fileName, function(exists)
    if (exists)
    fs.stat(fileName, function(error, stats)
    fs.open(fileName, "r", function(error, fd)
    var buffer = new Buffer(stats.size) ;

    fs.read(fd, buffer, 0, buffer.length, null, function(error, bytesRead, buffer)
    var data = buffer.toString("utf8", 0, buffer.length) ;

    console.log(data) ;
    fs.close(fd) ;
    ) ;
    ) ;
    ) ;
    ) ;

    Apparently, this kind of thing doesn’t raise an eyebrow in the JS world.

    Now, I understand and respect the JS programming model. But this was seriously frustrating when I first encountered it because a simple script like the one I was trying to write just has an ordered list of tasks to complete. When it asks for bytes from a file, it really has nothing better to do than to wait for the answer.

    Thankfully, it turns out that Node’s fs module includes synchronous versions of the various file access functions. So it’s all good.

    Conclusion
    I’m sure I missed or underexplained some things. But if other brave souls are interested in dipping their toes in the waters of Emscripten, I hope these tips will come in handy.