<?xml version="1.0" encoding="utf-8"?>
<!-- generator="Kukkaisvoima version 7" -->
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
>
<channel>
<title>vmx: geocouch-geospatial-queries-with-couchdb:2008-10-26:en,CouchDB,Python,geo</title>
<link>https://vmx.cx/cgi-bin/blog/index.cgi</link>
<description>Blog of Volker Mische</description>
<pubDate>Thu, 02 Apr 2026 23:02:11 +0200</pubDate>
<lastBuildDate>Thu, 02 Apr 2026 23:02:11 +0200</lastBuildDate>
<generator>http://23.fi/kukkaisvoima/</generator>
<language>en</language>
<item>
<title>Atmospheric data portals reply
</title>
<link>https://vmx.cx/cgi-bin/blog/index.cgi/atmospheric-data-portals-reply%3A2026-04-02%3Aen%2CMatadisco%2CATProto%2Cgeo</link>
<comments>https://vmx.cx/cgi-bin/blog/index.cgi/atmospheric-data-portals-reply%3A2026-04-02%3Aen%2CMatadisco%2CATProto%2Cgeo#comments</comments>
<pubDate>Thu, 02 Apr 2026 23:02:11 +0200</pubDate>
<dc:creator>Volker Mische</dc:creator>
<category>en</category>
<category>Matadisco</category>
<category>ATProto</category>
<category>geo</category>
<guid isPermaLink="false">https://vmx.cx/cgi-bin/blog/index.cgi/atmospheric-data-portals-reply%3A2026-04-02%3Aen%2CMatadisco%2CATProto%2Cgeo/</guid>
<description><![CDATA[ <p>This is a reply to <a href="https://bsky.app/profile/davidgasquez.com">David Gasquez’</a> blog post <a href="https://davidgasquez.com/atmospheric-data-portals">Atmospheric Data Portals</a>. As there’s so much in it and much of it overlaps with future plans, I thought it makes sense to write a proper public reply instead of following up in a private conversation.</p>
 [...]]]></description>
<content:encoded><![CDATA[
<p>This is a reply to <a href="https://bsky.app/profile/davidgasquez.com">David Gasquez’</a> blog post <a href="https://davidgasquez.com/atmospheric-data-portals">Atmospheric Data Portals</a>. As there’s so much in it and much of it overlaps with future plans, I thought it makes sense to write a proper public reply instead of following up in a private conversation.</p>
<p>First of all, read his blog post and follow the many links, there is so much to discover.</p>
<p>One re-occurring thing in the documents linked from the “issues on the earlier stages of the Open Data pipeline” section is that for most portals a static site should be sufficient. I fully agree with that. When it’s done properly, an automated rebuild of some parts when new data is added should work well. These days even <a href="https://lil.law.harvard.edu/blog/2025/10/24/rethinking-data-discovery-for-libraries-and-digital-humanities/">powerful client-sided search is possible</a>.</p>
<p>It’s a bit off-topic, but <a href="https://davidgasquez.com/barefoot-data-platforms">David’s Barefoot Data Platforms page</a> links to <a href="https://maggieappleton.com/home-cooked-software">Maggie Appleton’s Home Cooked Software and Barefoot Developers talk</a> linked. I highly recommend watching it, it was one of my favourite talks at the <a href="https://web.archive.org/web/20241003131259/https://www.localfirstconf.com/">Local-first Conference 2024</a>. I always wanted to blog about it, but never found the time.</p>
<p>But now to the concrete points David mentions. If anyone has ideas on how to make those things happen with Matadisco, please open issues on the <a href="https://github.com/ipfs-fdn/matadisco">main Matadisco repo</a>.</p>
<blockquote>
<p>Take inspiration from existing flexible standards like <a href="https://datapackage.org/standard/data-package/">Data Package</a>, <a href="https://github.com/mlcommons/croissant">Croissant</a>, and GEO ones for the core fields. Start with the smallest shared lexicon while leaving room for specialized extensions (sidecars?).</p>
</blockquote>
<p>I don’t think Matadisco should go into too much detail on specifying what the metadata should look like. Making one metadata standard to rule them all is destined to fail from my experience (<a href="https://en.wikipedia.org/wiki/Geospatial_metadata">ISO 19115/19139</a> anyone?). Though there might be a lowest common denominator, similar to what <a href="https://standard.site/">Standard.site is doing for long-form publishing</a>. In order to find out what that looks like, I propose that individual communities start by specifying Lexicons for their own needs. This could be done through tags, which I’ve outlined in the <a href="https://github.com/ipfs-fdn/matadisco/issues/3">Matadisco issue “Introducing tags for filtering and extension point”</a>.</p>
<blockquote>
<p>Split datasets from “snapshots”. Say, <code>io.datonic.dataset</code> holds long-term properties like <code>description</code> and points to <code>io.datonic.dataset.release</code> or <code>io.datonic.dataset.snapshot</code>, which point to the actual resources.</p>
</blockquote>
<p>Some kind of hierarchical relationship would be useful. <a href="https://github.com/TomNicholas/FROST">FROST</a>, which Matadisco drew a lot of inspiration from, is centred around <a href="https://icechunk.io/">IceChunk</a>, which also has the <a href="https://icechunk.io/en/v1.1.21/concepts/#snapshots">concept of snapshots</a>. But I don’t think we should stop at the concept of snapshots. In my original demo, I scrape a <a href="https://stacspec.org/">STAC catalogue</a> for <a href="https://documentation.dataspace.copernicus.eu/Data/SentinelMissions/Sentinel2.html#sentinel-2-level-2a-surface-reflectance">Sentinel-2 imagery</a>. Every new image is a new record. They are all part of the same <a href="https://github.com/radiantearth/stac-spec/blob/ec002bb93dbfa47976822def8f11b2861775b662/collection-spec/collection-spec.md">STAC collection</a>, so we could use a similar concept in Matadisco as well.</p>
<blockquote>
<p>Add an optional <a href="https://dasl.ing/cid.html">DASL-CID field</a> for resources so we “pin” the bytes.</p>
</blockquote>
<p>Yes, that’s something <a href="https://bsky.app/profile/mosh.bsky.social">@mosh</a> is keen to have. It’s not only useful for pinning things to a specific version, but also to make it possible to verify that the data you received is the one you expected. It sounds trivial, but the problem would be where to put it. Do you only hash the metadata record it points to? Do you hash the data container (if there’s one)? Or each resource a metadata record points to?</p>
<blockquote>
<p>Core lexicon should be as agnostic as possible!</p>
</blockquote>
<p>As mentioned above, it might be out of scope for Matadisco and for now it’s left to the individual communities.</p>
<blockquote>
<p>Bootstrap the catalog. There are many <a href="https://github.com/datonic/hub/blob/main/notes/related-projects.md#indexes">open indexes and organizations</a>. Crawl them!</p>
</blockquote>
<p>Indeed! My first two Matadisco producers are <a href="https://github.com/vmx/sentinel-to-atproto/">sentinel-to-atproto</a> crawling <a href="https://radiantearth.github.io/stac-browser/#/external/earth-search.aws.element84.com/v1/collections/sentinel-2-l2a">Element 84’s Earth Search STAC catalogue</a> and <a href="https://github.com/vmx/gdi-de-csw-to-atproto/">gdi-de-csw-to-atproto</a> crawling the <a href="https://gdk.gdi-de.org/">GeoNetwork instance of the official German geo metadata catalogue</a>.</p>
<blockquote>
<p>Integrate with external repositories. E.g., a service <a href="https://developers.google.com/search/docs/appearance/structured-data/dataset">that creates <code>JSON-LD</code> files</a> from the datasets it sees appearing on the Atmosphere so <a href="https://datasetsearch.research.google.com/">Google Datasets picks them up</a>. The same cron job could push data into Hugging Face or any other tool that people are already using in their fields.</p>
</blockquote>
<p>At first this would need to happen for each individual type of record, see the tags proposal above.</p>
<blockquote>
<p>Convince and work with high quality organizations doing something like this! I’d <a href="https://source.coop/harvard-lil/gov-data">definitely collaborate with <code>source.coop</code> for example</a>.</p>
</blockquote>
<p>That surely is the goal!</p>

]]></content:encoded>
<wfw:commentRss>https://vmx.cx/cgi-bin/blog/index.cgi/atmospheric-data-portals-reply%3A2026-04-02%3Aen%2CMatadisco%2CATProto%2Cgeo/feed/</wfw:commentRss>
</item>
<item>
<title>FOSSGIS 2026
</title>
<link>https://vmx.cx/cgi-bin/blog/index.cgi/fossgis-2026%3A2026-04-01%3Aen%2CMatadisco%2CATProto%2Cconference%2Cgeo</link>
<comments>https://vmx.cx/cgi-bin/blog/index.cgi/fossgis-2026%3A2026-04-01%3Aen%2CMatadisco%2CATProto%2Cconference%2Cgeo#comments</comments>
<pubDate>Wed, 01 Apr 2026 13:24:23 +0200</pubDate>
<dc:creator>Volker Mische</dc:creator>
<category>en</category>
<category>Matadisco</category>
<category>ATProto</category>
<category>conference</category>
<category>geo</category>
<guid isPermaLink="false">https://vmx.cx/cgi-bin/blog/index.cgi/fossgis-2026%3A2026-04-01%3Aen%2CMatadisco%2CATProto%2Cconference%2Cgeo/</guid>
<description><![CDATA[ <p>This is a short write-up on the <a href="https://www.fossgis-konferenz.de/2026/">FOSSGIS 2026 conference</a>. It’s a German speaking conference on free and open source geographic information systems and <a href="https://en.wikipedia.org/wiki/OpenStreetMap">OpenStreetMap</a>. So maybe a blog post in English spreads the word even wider.</p>
 [...]]]></description>
<content:encoded><![CDATA[
<p>This is a short write-up on the <a href="https://www.fossgis-konferenz.de/2026/">FOSSGIS 2026 conference</a>. It’s a German speaking conference on free and open source geographic information systems and <a href="https://en.wikipedia.org/wiki/OpenStreetMap">OpenStreetMap</a>. So maybe a blog post in English spreads the word even wider.</p>
<p>While being the biggest edition ever (1000 registrations on-site, 300 online) it was well run and organized as every year. It didn’t even feel larger than usual. The <a href="https://c3voc.de/">CCC video team</a> streamed live and <a href="https://media.ccc.de/c/fossgis2026">published the cut videos</a> the same day in outstanding quality as always.</p>
<p>I split this post into two sections, one about interesting talks for the geo world in general and then follow up discussions on my <a href="https://matadisco.org/">Matadisco</a> talk and <a href="https://atproto.com/">ATProto</a> in general.</p>
<h3 id="talks">Talks</h3>
<p>I’ve spent most of my time in hallway chatting with people as this is what matters most to me when I’m attending a conference in person. Nonetheless I’ve still managed to see some excellent talks.</p>
<h4 id="panel-discussion-on-digital-sovereignty-in-the-cloud">Panel discussion on digital sovereignty in the cloud</h4>
<p>The conference started with a <a href="https://pretalx.com/fossgis2026/talk/HG87KC/">high-class panel discussion on digital sovereignty in the cloud</a>. The public discussion on that topic is often centered around where servers are located. Though that doesn’t actually matter. US companies can be forced by their government to give access to the data independent of their physical location.</p>
<p>Other topics touched were best practices on switching from proprietary to open source systems.</p>
<h4 id="barrier-free-travelling-thanks-to-paid-mappers">Barrier-free travelling thanks to paid mappers</h4>
<p>Public transport in Germany must be accessible to disabled individuals (reality is far away from that). For routing, you need the data basis for it. This talk gets into the details on how <a href="https://en.wikipedia.org/wiki/Baden-W%C3%BCrttemberg">Baden-Württemberg</a>, a federal state in south Germany, works on enabling <a href="https://pretalx.com/fossgis2026/talk/V7YYG9/">barrier-free travelling</a>. They decided to add that information of all their 1100 train stations directly to OpenStreetMap. In order to achieve the required high quality they’ve hired through a third party company several experienced mappers from the community.</p>
<p>I really like the idea that OpenStreetMap can now be used as source of truth for that data set. I hope other federal states follow this lead.</p>
<h4 id="routing-talks">Routing talks</h4>
<p>I’ve seen two talks about routing. The one about <a href="https://pretalx.com/fossgis2026/talk/NHZTAM/">Valhalla routing engine with MapLibre Native</a> was interesting because it was about a special case, where you want to re-route bus lines in case of construction. Although the resulting system is not open source, they’ve contributed upstream to <a href="https://github.com/valhalla/valhalla">Valhalla</a>, to make it work well with <a href="https://github.com/maplibre/maplibre-native">MapLibre Native</a>. Those contributions can be more valuable than a one time source code dump of forked repositories, just to call it open source.</p>
<p>Another one was about <a href="https://pretalx.com/fossgis2026/talk/FNSWK8/">Real-time mobility analytics for disaster relief operations</a>, which was interesting to see how routing is used in such cases. The limitations and how such systems really help on the ground.</p>
<h3 id="matadisco-and-atproto">Matadisco and ATProto</h3>
<p>My <a href="https://pretalx.com/fossgis2026/talk/KV8VC7/">talk on Matadisco</a> was about the current status of metadata catalogues, the problems and how ATProto can make things better. What I should have made clearer is what Matadisco actually is. I didn’t make it clear that it’s just a schema/convention people would use to announce their data on ATProto. It could’ve been mistaken as a piece of software or a service. You would use Matadisco in order to implement something for your pipeline.</p>
<p>Nonetheless people got the idea and I had good conversations afterwards. I talked with <a href="https://bsky.app/profile/oliviaguyot.bsky.social">Olivia Guyot</a> about the possible ways on how to integrate Matadisco record publishing into <a href="https://geonetwork-opensource.org/">GeoNetwork</a>. With <a href="https://bsky.app/profile/cwillmes.mastodon.social.ap.brid.gy">Christian Willmes</a> about creating a portal for combining paleoenvironmental and archaeological data.</p>
<p>While chatting about ATProto at one of the social events <a href="https://bsky.app/profile/lapizistik.social.tchncs.de.ap.brid.gy">Klaus Stein</a> talked about how he would like a social network to be. Users would just put static files somewhere. I agree that having static webspace somewhere without any server component is not only cheap, but also the easiest to get. He is not bothered about other components being operated by other parties, e.g. for indexing. That kept me thinking how far ATProto is away from that. I’d like to build a prototype that is like a static site generator for ATProto records. It won’t be able to act as a full PDS, you would need a WebSocket connection to get the data to a relay. But there could be a minimal service operated by a third party that polls those static PDS for updates and forwards them to a relay.</p>

]]></content:encoded>
<wfw:commentRss>https://vmx.cx/cgi-bin/blog/index.cgi/fossgis-2026%3A2026-04-01%3Aen%2CMatadisco%2CATProto%2Cconference%2Cgeo/feed/</wfw:commentRss>
</item>
<item>
<title>Matadisco
</title>
<link>https://vmx.cx/cgi-bin/blog/index.cgi/matadisco%3A2026-03-23%3Aen%2CATProto%2Cgeo</link>
<comments>https://vmx.cx/cgi-bin/blog/index.cgi/matadisco%3A2026-03-23%3Aen%2CATProto%2Cgeo#comments</comments>
<pubDate>Mon, 23 Mar 2026 16:58:12 +0200</pubDate>
<dc:creator>Volker Mische</dc:creator>
<category>en</category>
<category>ATProto</category>
<category>geo</category>
<guid isPermaLink="false">https://vmx.cx/cgi-bin/blog/index.cgi/matadisco%3A2026-03-23%3Aen%2CATProto%2Cgeo/</guid>
<description><![CDATA[ <p>Open data is only as useful as it is discoverable. Finding datasets, whether it’s satellite imagery, scientific research, or cultural archives involves navigating dozens of siloed portals, each of them with different interfaces and APIs. Project <a href="https://matadisco.org/">Matadisco</a> tries to solve this by using <a href="https://atproto.com/">ATProto</a> to create an open, decentralized network for data discovery. Anyone can publish metadata about their datasets. You can then pick the records that matter to you and build views for the specific needs of your community. By focusing on metadata rather than the data itself, the system works with any dataset format, keeps records lightweight, and remains agnostic about storage.</p>
 [...]]]></description>
<content:encoded><![CDATA[
<p>Open data is only as useful as it is discoverable. Finding datasets, whether it’s satellite imagery, scientific research, or cultural archives involves navigating dozens of siloed portals, each of them with different interfaces and APIs. Project <a href="https://matadisco.org/">Matadisco</a> tries to solve this by using <a href="https://atproto.com/">ATProto</a> to create an open, decentralized network for data discovery. Anyone can publish metadata about their datasets. You can then pick the records that matter to you and build views for the specific needs of your community. By focusing on metadata rather than the data itself, the system works with any dataset format, keeps records lightweight, and remains agnostic about storage.</p>
<p>It’s early stage and experimental, but the potential is significant. To see it in action, visit the <a href="https://vmx.github.io/matadisco-viewer/">matadisco-viewer demo</a>. It listens to the incoming stream of ATProto events and renders them. At the moment it’s satellite images only, but that will hopefully change soon.</p>
<p><a href="/blog/2026-03-23/S2C_35NRB_20260121_0_L2A-TCI_page3.jpg"><img src="/blog/2026-03-23/S2C_35NRB_20260121_0_L2A-TCI_small.jpg" alt="Satellite image" /></a></p>
<p>Above is an example of what crossed my screen while developing (<a href="https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a/items/S2C_35NRB_20260121_0_L2A">metadata</a>, <a href="https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/35/N/RB/2026/1/S2C_35NRB_20260121_0_L2A/TCI.tif">download at full resolution (253MiB)</a>).</p>
<h2 id="motivation">Motivation</h2>
<p>Metadata records can be very diverse. They might describe geodata, your favourite news site or your favourite podcasts. What they all have in common is that users usually rely on centralized platforms in order to find them. For geodata, this is often a government-run open data or geo portal. These platforms decide which data gets published.</p>
<p>You might generate a derived dataset or clean up an existing one. If you operate from outside of the original creators, you probably won’t even be able to get your data linked from there. So how will anyone find out about it? That’s a problem of metadata discovery.</p>
<p>The other side of the problem is that even when metadata <em>is</em> available, it can be hard to find. There are large metadata aggregation portals like the <a href="https://data.europa.eu/">portal for European data</a>, with almost 2 million records. How do you find what exactly you are looking for. What if there were specialized portals tailored to specific communities?</p>
<p>For even more details, see the <a href="https://ipfsfoundation.org/matadisco-can-we-bootstrap-public-data-discovery-with-atproto/">companion blog post of the IPFS Foundation</a>.</p>
<h2 id="the-idea">The idea</h2>
<p>The idea is to support both: an easy way for anyone to publish discoverable metadata, and a way to make that metadata widely accessible to build both large aggregators and specialized portals tailored to specific communities.</p>
<p>The central building block is <a href="https://atproto.com/">ATProto</a>. It allows anyone to publish and subscribe to records. Rather than defining a single metadata schema to rule them all, the approach here is more meta-meta. Each record contains a link to the actual metadata. That’s the absolute minimum. Though it could make sense to go beyond this minimalism and store additional information to make it easier to build custom portals.</p>
<p>One example of such additional information is a preview. It’s nice to get a quick sense of the underlying data that the metadata describes. For satellite imagery, this could be a true color thumbnail of the scene. For long form articles, a summary or excerpt. For podcasts it may be a brief audio snippet or trailer.</p>
<h2 id="the-implementation">The implementation</h2>
<p>As part of my work at the <a href="https://ipfsfoundation.org/">IPFS Foundation</a>, I started with geodata. The first prototype focuses on [Copernicus Sentinel-2 L2A satellite images].</p>
<p>The metadata is sourced from <a href="https://radiantearth.github.io/stac-browser/#/external/earth-search.aws.element84.com/v1/collections/sentinel-2-l2a">Element 84’s Earth Search STAC catalogue</a>. It provides free, publicly accessible HTTP links to the images (the <a href="https://radiantearth.github.io/stac-browser/#/external/stac.dataspace.copernicus.eu/v1/collections/sentinel-2-l2a">official Copernicus STAC</a> does not). A [Cloudflare Worker] checks the STAC instance every few minutes for updates. When new records appear, a link to the metadata along with a preview is ingested into ATProto. The source code for the worker is available at <a href="https://github.com/vmx/sentinel-to-atproto/">https://github.com/vmx/sentinel-to-atproto/</a>.</p>
<p>Below is the Lexicon schema for this ATProto meta-metadata record, which I call Matadisco. To improve readability, the <a href="https://mlf.lol/playground/?share=Ly8vIEEgTWF0YWRpc2NvIHJlY29yZApyZWNvcmQgbWF0YWRpc2NvIHsKICAgIC8vLyBUaGUgdGltZSB0aGUgb3JpZ2luYWwgbWV0YWRhdGEvZGF0YSB3YXMgcHVibGlzaGVkCiAgICBwdWJsaXNoZWRBdCE6IERhdGV0aW1lLAogICAgLy8vIEEgVVJJIHRoYXQgbGlua3MgdG8gcmVzb3VyY2UgY29udGFpbmluZyB0aGUgbWV0YWRhdGEKICAgIHJlc291cmNlITogVXJpLAogICAgLy8vIFByZXZpZXcgb2YgdGhlIGRhdGEKICAgIHByZXZpZXc6IHsKICAgICAgICAvLy8gVGhlIG1lZGlhIHR5cGUgdGhlIHByZXZpZXcgaGFzCiAgICAgICAgbWltZVR5cGUhOiBzdHJpbmcsCiAgICAgICAgLy8vIFRoZSBVUkwgdG8gdGhlIHByZXZpZXcKICAgICAgICB1cmw6IFVyaSwKICAgIH0sCn0K">MLF syntax</a> is used:</p>
<pre><code>/// A Matadisco record
record matadisco {
    /// The time the original metadata/data was published
    publishedAt!: Datetime,
    /// A URI that links to resource containing the metadata
    resource!: Uri,
    /// Preview of the data
    preview: {
        /// The media type the preview has
        mimeType!: string,
        /// The URL to the preview
        url: Uri,
    },
}
</code></pre>
<p>Once records are available on ATProto, they can be processed and displayed. I built a simple viewer that renders records conforming to the <code>cx.vmx.matadisco</code> Lexicon schema defined above. A <a href="https://github.com/bluesky-social/jetstream">Bluesky Jetstream</a> instance streams newly added records directly into the browser. A demo is available at <a href="https://vmx.github.io/matadisco-viewer/">https://vmx.github.io/matadisco-viewer/</a>.</p>
<p>If you’re interested in seeing the raw records, you can find them <a href="https://pdsls.dev/at://did:plc:otu6ccrwycke33kl3h4yjhwn/cx.vmx.matadisco">on my ATProto dev account</a>.</p>
<h2 id="prior-art">Prior art</h2>
<p>This work builds on ideas by <a href="https://github.com/TomNicholas/">Tom Nicholas</a>, who started a project called <a href="https://github.com/TomNicholas/FROST">FROST</a>. His <a href="https://hackmd.io/@TomNicholas/H1KzoYrPJe">motivating blog post</a> is an excellent read about data-sharing challenges in a scientific context. His <a href="https://discourse.pangeo.io/t/pangeo-showcase-frost-federated-registry-of-scientific-things-feb-12-2025/4861">presentation on FROST</a> explains why such a system should remain simple, with the metadata URL as the only required field.</p>
<p><a href="https://github.com/edsilv">Edward Silverton</a>, who works in the <a href="https://en.wikipedia.org/wiki/GLAM_(cultural_heritage)">GLAM</a> space, explored a similar idea for publishing <a href="https://en.wikipedia.org/wiki/International_Image_Interoperability_Framework">IIIF</a> data. We refined his approach to align it more closely with FROST. <a href="https://docs.google.com/document/d/1CylRKwnnWsnGQS4enAf4xihz8wmjf3CEGcT1gwwz1PM/edit?usp=sharing">He published</a> further details on the complete workflow for his use case, which has a broader scope.</p>
<p>There was also a discussion thread on Bluesky about <a href="https://bsky.app/profile/brookie.blog/post/3m6uu3emkwc2s">metadata for long-form content to build cross-platform discovery</a>.</p>
<h2 id="whats-next">What’s next</h2>
<p>Possible future steps I want to look into:</p>
<ul>
<li>Adding another, different geodata source, such as metadata from the <a href="https://geodatenkatalog.de">German geodata catalogue</a>.</li>
<li>Including another image-based source, for example GLAM catalogues that use <a href="https://en.wikipedia.org/wiki/International_Image_Interoperability_Framework">IIIF</a>.</li>
<li>Integrating a completely different data source, such as metadata from the <a href="https://www.ardaudiothek.de/">podcasts of the German public broadcasting</a>.</li>
</ul>
<p>As mentioned in the introduction, this is deliberately experimental, things may break or change dramatically. The upside is that no one needs to worry about breakage. Please experiment with these ideas and let us now about them at the <a href="https://github.com/ipfs-fdn/matadisco">Matadisco GitHub repository</a>. Publish records under your own namespace, or even reuse the one I am currently using.</p>

]]></content:encoded>
<wfw:commentRss>https://vmx.cx/cgi-bin/blog/index.cgi/matadisco%3A2026-03-23%3Aen%2CATProto%2Cgeo/feed/</wfw:commentRss>
</item>
<item>
<title>FOSS4G 2023
</title>
<link>https://vmx.cx/cgi-bin/blog/index.cgi/foss4g-2023%3A2023-07-22%3Aen%2CIPFS%2Cconference%2Cgeo</link>
<comments>https://vmx.cx/cgi-bin/blog/index.cgi/foss4g-2023%3A2023-07-22%3Aen%2CIPFS%2Cconference%2Cgeo#comments</comments>
<pubDate>Sat, 22 Jul 2023 21:50:07 +0200</pubDate>
<dc:creator>Volker Mische</dc:creator>
<category>en</category>
<category>IPFS</category>
<category>conference</category>
<category>geo</category>
<guid isPermaLink="false">https://vmx.cx/cgi-bin/blog/index.cgi/foss4g-2023%3A2023-07-22%3Aen%2CIPFS%2Cconference%2Cgeo/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[

<p>Finally, after missing one virtual and one in person global <a href="https://2023.foss4g.org/">FOSS4G</a> I had again the chance to attend a global in-person FOSS4G conference. Thanks <a href="https://protocol.ai/">Protocol Labs</a> for sending me. This year it was in <a href="https://en.wikipedia.org/wiki/Prizren">Prizren, Kosovo</a>. I’m a bit late with that post, but that’s due to doing some hiking in Albania right after the conference.</p>

<h3 id="the-organization-and-venue">The organization and venue</h3>

<p>Wow. It’s been my favourite venue of all FOSS4Gs I’ve been to so far. The exhibition hall was a great place to hang out, combined with the excellent idea of a 24h bar. I’m not sure if it was used at all times, but definitely for more than 20h a day. Outside, there was plenty of space and tables to hang out, and very close by another set of tables that formed the “work area”. Which was another great place to hang out, with enough power sockets and shade for the hot days.</p>

<p>The main stage was an open air stage with enough seating for everyone. It was converted for the gala dinner to a stage with an excellent live band and the usual big round tables.</p>

<p>For me, the best part was that even the accommodation was on-site. The barracks of the former military basis, which now serve as student dorms, were our home for a week. Pretty spartan, but at a conference I don’t really spend much time in my room, I mostly need just some place to sleep.</p>

<p>Having everything, the talks, exhibition, social events and accommodations on-site makes it easy to maximize the time for socializing, which for me is the number one reason to attend a conference.</p>

<p>Everything was well organized, and it was great to see so many volunteers around.</p>

<h3 id="the-talks">The talks</h3>

<p>I haven’t really selected the talks I went to. I rather joined others where they were going, or listened to recommendations. Often, I just stayed in the rest of the slot to see what else is there. My favourite talks were:</p>

<ul>
<li><a href="https://talks.osgeo.org/foss4g-2023/talk/DWCZBQ/">Smart Maps for the UN and All - keeping web maps open</a>: For me, it was the first time I saw someone speaking at a FOSS4G about using <a href="https://ipfs.tech/">IPFS</a> that wasn’t me. It’s great to see that it gains traction for the offline use case, where it just makes a lot of sense. <a href="https://github.com/UNopenGIS/7">UN Smart Maps</a> is part of the <a href="http://unopengis.org/">UN OpenGIS initiative</a>, it features a wide range of things, even an AI chatbot called <a href="https://github.com/yuiseki/TRIDENT">TRIDENT</a> that transforms the text into <a href="https://overpass-api.de/">Overpass API</a> calls. <a href="https://trident.yuiseki.net/">Try TRIDENT it out yourself</a>, when you open the developer console, you can see the resulting Overpass API calls.</li>
<li><a href="https://talks.osgeo.org/foss4g-2023/talk/B9DDED/">Offline web map server “UNVT Portable”</a>: This talk got into more detail about using Raspberry Pis to have map data stored in IPFS for offline use. It’s very similar to what I envision, the only difference is that I’d also like to keep the storage in the browser. But I surely see a future, where those efforts are combined, to have a small easy server you can deploy, with in browser copies of subsets of the data to be able to work completely offline in the field. The <a href="https://github.com/unvt/portable">original UNVT Portable repository</a> doesn’t use IPFS, but <a href="https://github.com/UNopenGIS/smb">Smart Maps Bazaar</a> does, which seems to be its successor.</li>
<li><a href="https://talks.osgeo.org/foss4g-2023/talk/A3AJPJ/">B6, Diagonal’s open source geospatial analysis engine</a>: A presentation of the <a href="https://github.com/diagonalworks/diagonal-b6">B6 tool for geospatial analysis for urban planning</a>. It has a beautiful interface. I really like the idea of doing things directly on the map in a notebook-style way, where you perform certain steps after each other.</li>
<li><a href="https://talks.osgeo.org/foss4g-2023/talk/N7DXXW/">Elephant in the room</a>: A talk about how many resources to computations take? Do we always need it? It’s very hard, often impossible, to find out how environmentally friendly some cloud services are. One of the conclusions was that cheaper providers likely use less power, hence are harming the environment less. I would like if there would be better ways (e.g. it misses things like economies of scale of large providers), but I agree that this might be the best metric we currently have. And I also hope there will be more economic pressure to save resources.</li>
<li>There was a closing keynote from <a href="https://twitter.com/KyoungSooEom">Kyoung-Soo Eom</a>, who was talking about his long journey in open source GIS, but also his history with Kosovo, where he was also <a href="https://twitter.com/eeeestein/status/1674885091573760001">on a mission in 1999</a>. Quite inspiring.</li>
</ul>

<h3 id="my-talk">My talk</h3>

<p>My talk about <a href="https://talks.osgeo.org/foss4g-2023/talk/YL8DVJ/">Collaborative mapping without internet connectivity</a> was about a browser based offline-first prototype that uses IPFS to enable replication to other peers. The project is called <a href="https://github.com/vmx/colleemap">Colleemap</a> and is dual-licensed under the MIT and Apache 2.0 license. Although I tried the demo bazillion times before my talk, it sadly didn’t work during my talk. Though, trying it later with various people, I was able to get 4 peers connected once. I even saw it <a href="https://twitter.com/yuiseki_/status/1675152146457587715">working on a Windows machine</a>. So it really works cross-platform.</p>

<p>For the future I hope to work closer with the people from the <a href="http://unopengis.org/">UN OpenGIS initiative</a>, it would be great to combine it with their Raspberry Pi based prototype.</p>

<h3 id="things-ive-learnt">Things I’ve learnt</h3>

<p>The <a href="https://sentinel.esa.int/web/sentinel/missions/sentinel-2">Sentinel-2 satellite imagery</a> is available from multiple sources, directly from <a href="https://scihub.copernicus.eu/">Copernicus Open Access Hub</a> or through cloud providers like AWS, Azure of Google Cloud. From the cloud providers you only get the <a href="https://sentinels.copernicus.eu/web/sentinel/user-guides/sentinel-2-msi/processing-levels/level-2">level-2 data</a>. They might use the original level-2 data or do their own <a href="https://en.wikipedia.org/wiki/Atmospheric_correction">atmospheric correction</a> based on the <a href="https://sentinels.copernicus.eu/web/sentinel/user-guides/sentinel-2-msi/processing-levels/level-1">level-1 data</a>. Or even re-encode the data. So it’s hard to tell which kind of data you actually get.</p>

<p>As far as I know (please let me know if I’m wrong), there isn’t any mirror of the full level-1c data. You can only get it through the Copernicus Open Access Hub and there the older images are stored in the long term archive on tape, where it can take up to 24h for the data to be available for download (if it works).</p>

<p>Ideally, there would be a mirror of the full level-1c data (where the ESA would provide checksums of their files) and a level-2 version, where the exact process is openly published, so that you can verify how it was created. The problem is the storage cost. The current level-2 data is about 25 PiB, which leads to storage costs of over $500k USD a month if you would store it on AWS S3 Standard at the current pricing (I used the $0.021 per GB).</p>

<h3 id="final-thoughts">Final thoughts</h3>

<p>It was great to meet <a href="https://twitter.com/GresaNeziri">Gresa</a> and <a href="https://twitter.com/mustafavalmir">Valmir</a> from the local organizing committee before the FOSS4G in March at the OSGeo German language chapter conference <a href="https://www.fossgis-konferenz.de/">FOSSGIS</a> in Berlin. That made it easy for me to connect to the event right from the start. If there’s one thing future FOSS4Gs should adapt, it’s the cheap on-site (or close by) accommodation. I think that shared bathrooms is also much smoother to have, if you know that everyone in the accommodation is from the conference. We had something similar with the <a href="https://www.basecamp-bonn.de/">BaseCamp</a> in Bonn during the FOSS4G 2016 and the international code spring in 2018 during the FOSSGIS conference, where the whole place was rented for the time of the events.</p>

<p>Though, of course, I also missed some of my longtime FOSS4G friends I hadn’t seen in a long time. I hope you’re all doing well and will meet again soon.</p>

]]></content:encoded>
<wfw:commentRss>https://vmx.cx/cgi-bin/blog/index.cgi/foss4g-2023%3A2023-07-22%3Aen%2CIPFS%2Cconference%2Cgeo/feed/</wfw:commentRss>
</item>
<item>
<title>Video uploads for an online conference
</title>
<link>https://vmx.cx/cgi-bin/blog/index.cgi/video-uploads-for-an-online-conference%3A2021-06-12%3Aen%2Cconference%2Cgeo</link>
<comments>https://vmx.cx/cgi-bin/blog/index.cgi/video-uploads-for-an-online-conference%3A2021-06-12%3Aen%2Cconference%2Cgeo#comments</comments>
<pubDate>Sat, 12 Jun 2021 16:35:47 +0200</pubDate>
<dc:creator>Volker Mische</dc:creator>
<category>en</category>
<category>conference</category>
<category>geo</category>
<guid isPermaLink="false">https://vmx.cx/cgi-bin/blog/index.cgi/video-uploads-for-an-online-conference%3A2021-06-12%3Aen%2Cconference%2Cgeo/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[

<p>This blog post should give some insights on what happens behind the scenes in preparation of an online conference, and I also hope that some of the scripts I created might be useful for others as well. We were using <a href="https://pretalx.com/">pretalx</a> for the submissions and <a href="https://seafile.com/">Seafile</a> for video uploads. Both systems are accessed over their HTTP API.</p>

<p>This year’s <a href="https://www.fossgis-konferenz.de/2021/">FOSSGIS 2021 conference</a> was a pure online conference. Though it had the same format as every year. Three days of conference, with four tracks in parallel. This leads to about 100 talks. I joined the organizing team about 10 weeks before the conference took place. The task sounded easy. The speakers should be able to upload their talks prior to the conference, so that during the conference less could go wrong.</p>

<p>All scripts are available at <a href="https://github.com/vmx/conference-tools">https://github.com/vmx/conference-tools</a> licensed under the <a href="https://opensource.org/licenses/MIT">MIT License</a>.</p>

<h3 id="the-software">The software</h3>

<p>The speakers submitted their talks through <a href="https://pretalx.com/">pretalx</a>, a conference management system I highly recommend. It is open source and has an active community. I’ve worked on/with it over the past few to make it suitable for <a href="https://osgeo.org/">OSGeo</a> conferences. The latest addition is the <a href="https://github.com/pretalx/pretalx-public-voting">public community voting plugin</a>, which has been used for the <a href="https://2021.foss4g.org/">FOSS4G 2021</a> as well as this conference. pretalx has a great HTTP API to get data out of the system. It doesn’t yet have much support for manipulating the data, but pull-requests are welcome.</p>

<p>For storing the video files, <a href="https://seafile.com/">Seafile</a> was used. I haven’t had any prior experience with it. It took me a bit to figure out, that the Python API is for local access only and that the public API is a pure HTTP API. You can clearly see that their API is tailored to their use in their web interface and not really designed for third party usage. Nonetheless, it guarantees that you can do everything via the HTTP API, that can be done through the web UI.</p>

<p>My scripts are heavily based on command line tools like <a href="https://www.gnu.org/software/coreutils/manual/html_node/b2sum-invocation.html">b2sum</a>, <a href="https://curl.se/">curl</a>, <a href="https://en.wikipedia.org/wiki/Cut_(Unix)">cut</a>, <a href="https://stedolan.github.io/jq/">jq</a> and <a href="https://github.com/jpmens/jo">jo</a>, hence a lot of shell is used. For more complex data manipulation, like merging data, I use <a href="https://python.org/">Python</a>.</p>

<h3 id="the-task">The task</h3>

<p>The basic task is providing pre-recorded videos for a conference that were uploaded by the speakers themselves. The actual finer grained steps are:</p>

<ul>
  <li>Sending the speakers upload links</li>
  <li>Looking through the videos to make sure they are good</li>
  <li>Re-organizing the files suitable to be played back according to the schedule</li>
  <li>Make the final files easily downloadable</li>
  <li>Create a schedule which lists the live/pre-recorded talks</li>
</ul>

<h4 id="sending-upload-links">Sending upload links</h4>

<p>In Seafile you can create directories and make them publicly available so that people can upload files. Once uploaded, you won’t see what else in that directory. In order to be able to easily reference the uploaded videos back to the corresponding talk, it was important to create one dedicated directory per talk, as you won’t know which filenames people will use for their videos.</p>

<p>The speakers will receive an email containing dedicated upload links for each of their talks. See the <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/email_upload_links"><code>email_upload_links</code></a> directory for all the scripts that are needed for this step.</p>

<h5 id="pretalx">pretalx</h5>

<p>First you need to get all the talks. In pretalx that’s easy, go to your conference, e.g. <a href="https://pretalx.com/api/events/democon/submissions/">https://pretalx.com/api/events/democon/submissions/</a>. We only care about the accepted talks, which can be done with selecting a filter. If you access it through curl, you’ll get a JSON response like that one: <a href="https://pretalx.com/api/events/democon/submissions/?format=json">https://pretalx.com/api/events/democon/submissions/?format=json</a>. pretalx returns 25 results per request. I’ve created a script called <a href="https://gist.github.com/vmx/02d1ee691d681274b4387510f8e0b5f0/"><code>pretalx-get-all.py</code></a> that automatically pages through all the results and concatenates them.</p>

<p>A talk might be associated with multiple speakers. Each speaker should get an email with an upload link. There were submissions that are not really talks in the traditional sense, so people shouldn’t get an email. The query for jq looks like that:</p>

<p><code>
[.results[] | select((.submission_type[] | contains("Workshop")) or (.submission_type[] == "Anwendertreffen / BoF") | not) | { code: .code, speaker: .speakers[].code, title: .title, submission_type: .submission_type[]}]
</code></p>

<p>The submissions contain only the speaker IDs and names, but not other details like their email address. We query the speakers API (e.g. https://pretalx.com/api/events/democon/speakers/) and post-process the data again with jq, as we care about their email addresses.</p>

<p>You can find all the requests and filter in the <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/email_upload_links/upload_talks_to_seafile.sh"><code>email_upload_links/upload_talks_to_seafile.sh</code> script</a>.</p>

<h5 id="seafile">Seafile</h5>

<p>Creating and upload link is a two-step process in Seafile. First create the directory, then creating a public accessible upload link for the directory. The directories are named after the pretalx ID of the talk (<a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/email_upload_links/createdirs.sh">Full script for creating directories</a>).</p>

<h5 id="creating-emails">Creating emails</h5>

<p>After acquiring the data, the next step is to process the data and creating the individual emails. Combining the data is done with the <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/email_upload_links/combine_talks_speakers_upload_links.py"><code>combine_talks_speakers_upload_links.py</code> script</a>, where the output is again post-processed with jq. The <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/email_upload_links/data_to_email.py"><code>data_to_email.py</code> script</a> takes that data output and a template file to create the actual email as files. The template file is used as a <a href="https://docs.python.org/3/library/string.html#format-string-syntax">Python format string</a>, where the variables a filled with the data provided.</p>

<p>Those email files are then posted to pretalx, so that we can send them over their email system. That step is more complicated as currently there is no API in pretalx to do that. I logged in through the web interface and manually added a new email, while having the developer tools open. I then copied the <code>POST</code> request “as cURL” to have a look at the data it sent. There I manually extracted the session and cookie information in order to add emails from the command line. The script that takes the pre-generated emails and puts them into pretalx is called <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/email_upload_links/email_to_pretalx.sh"><code>email_to_pretalx.sh</code></a>.</p>

<h3 id="reviewing-the-uploaded-videos">Reviewing the uploaded videos</h3>

<p>Once a video is uploaded, it gets reviewed. The idea was, that the speakers don’t need to care too much about the start and the end of the video, e.g. when they start the recording and there is a few seconds of silence while switching to the presentation. The reviewer will cut the beginning and end of the video and also convert it to a common format.</p>

<p>We wanted to preserve the original video quality, hence we use <a href="https://mifi.no/losslesscut/">LosslessCut</a> and converted it then to the <a href="https://matroska.org/">Matroska format</a>. The reviewers would also check that the video isn’t longer than the planned slot.</p>

<p>See the <a href="https://github.com/vmx/conference-tools/tree/c06bd2bd8df64f992ffece37c6616732ee1a9f62/copy_uploads"><code>copy_uploads</code></a> directory for all the scripts that are needed for this step.</p>

<h4 id="pretalx-1">pretalx</h4>

<p>The reviewers get a file with things to check for each video file. We get the needed metadata again from pretalx and post-process it with jq. As above for the emails, there is again a template file which (this time) generates Markdown files with the information for the reviewers. The full script is called <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/copy_uploads/create_info_files.sh"><code>create_info_files.sh</code></a>.</p>

<h4 id="seafile-1">Seafile</h4>

<p>Once videos are uploaded they should be available for the reviewers. The uploaded files are the primary source, hence it makes sense to always make copies of the talks, so that the original uploads are not lost. The <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/copy_uploads/sync_files_and_upload_info.sh"><code>sync_files_and_upload_info.sh</code> script</a> copies the talks into a new directory (together with the information files), which is then writeable for the reviewers. They will download the file, review it, cut it if needed, convert it to Matroska and upload it again. Once uploaded, they move the directory into one called <code>fertig</code> (“done” in German) as an indicator that no one else needs to review it.</p>

<p>I run the script daily as a cron job, it only copies the new uploads. Please note that it only checks the existence on a directory level. This means that if a talk was reviewed and a speaker uploads a new version of the talk, it won’t be copied. That case didn’t often happen often and speakers actually let us know about it, so it’s mostly a non-issue (also see the <a href="#number-of-uploads">miscellaneous scripts section</a> for more).</p>

<p>Last step is that someone looks through the filled out markdown files to check if everything was alright, respectively make sure that e.g. the audio volume is fixed, or asks the speaker for a new upload. The then checked videos are moved to yet another directory, which then contains all the talks that are ready to be streamed.</p>

<h3 id="re-org-files-for-schedule">Re-org files for schedule</h3>

<p>So far, the video files were organized by directories that are named after the pretalx ID of the talk. For running the conference we used <a href="https://obsproject.com/">OBS</a> for streamer. The operator would need to play the right video at the right time. Therefore, it makes sense to sort them by the schedule. The <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/cut_to_schedule/cut_to_schedule.sh"><code>cut_to_schedule.sh</code> script</a> does that re-organization, which can be found in the <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/cut_to_schedule/"><code>cut_to_schedule</code> directory</a>.</p>

<h4 id="pretalx-2">pretalx</h4>

<p>To prevent accidental inconsistencies, the root directory is named after the current version of the pretalx schedule. So if you publish a new version of the schedule and run the script again, you’ll get a new directory structure. The video files still have an arbitrary name, chosen by the uploader/reviewer, we want a common naming scheme instead. The <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/cut_to_schedule/get_filepath.py"><code>get_filepath.py</code> script</a> creates such a name that also sorts chronologically and contains all the information the OBS operators need. The current scheme is <code>&lt;room&gt;/day&lt;day-of-the-conference&gt;/day&lt;day-of-the-conference&gt;_&lt;day-of-the-week&gt;_&lt;date&gt;_&lt;time&gt;_&lt;pretalx-id&gt;_&lt;title&gt;.mkv</code>.</p>

<h4 id="seafile-2">Seafile</h4>

<p>The directories do not only contain the single final video, but also the metadata and perhaps the original video or a presentation. The file we actually copy is the <code>*.mkv</code> file which was modified last, which will be the cut video. The <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/cut_to_schedule/get_files_to_copy.sh"><code>get_files_to_copy.sh</code> script</a> creates a list of the files that should be copied, it will only list the files that weren’t copied yet (based on the filename). The <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/cut_to_schedule/copy_files.sh"><code>copy_files.sh</code> script</a> does the actual copying and is rather generic, it only depends on a file list and Seafile.</p>

<h3 id="easily-downloadable-files">Easily downloadable files</h3>

<p>Seafile has a feature to download a full directory as zip file. I originally planned to use that. It turns out that the size of the files can be too large, I got the error message <code>Unable to download directory "day1": size is too large.</code>. So I needed to provide another tool, as I didn’t want that people would need to click and download all individual talks.</p>

<p>The access to the files should as easy as possible, i.e. the operators that need the files shouldn’t need a Seafile account. As the videos also shouldn’t be public, the compromise was using a download link secured with a password. This means that an authentication step is needed, which isn’t trivial. The <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/download_files/download_files.sh"><code>download_files.sh</code> script</a> does login and then downloads all the files in that directory. For simplicity, it doesn’t do recursively. This means that any stage would need to run this script for each day.</p>

<p>I also added a checksum check for more robustness. I created those checksums manually with running <code>b2sum * &gt; B2SUMS</code> in each of the directories and then uploaded them to Seafile.</p>

<h3 id="list-of-livepre-recorded-talks">List of live/pre-recorded talks</h3>

<p>Some talks are recorded and some are live, the <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/list_prerecorded_talks/list_recorded_talks.py"><code>list_recorded_talks.py</code> script</a>, creates a Markdown file that contains a schedule with that information, including the lengths of the talks if they are pre-recorded. This is useful for the moderators to know how much time for questions will be. At the FOSSGIS we have 5 minutes for questions, but if the talk runs longer, there will be less time.</p>

<p>You need the schedule and the length of the recorded talks. This time I haven’t fully automated the process, it’s a bit more manual than the other steps. All scripts can be found in the <a href="https://github.com/vmx/conference-tools/tree/c06bd2bd8df64f992ffece37c6616732ee1a9f62/list_prerecorded_talks"><code>list_recorded_talks</code> directory</a>.</p>

<p>Get the schedule:</p>

<pre><code>curl https://pretalx.com/&lt;your-conference&gt;/schedule.json &gt; schedule.json
</code></pre>

<p>For getting the lengths of the videos, download them all with the download script from the <a href="#easily-downloadable-files">Easily downloadable files</a> section above. Then run the <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/list_prerecorded_talks/get_length.sh"><code>get_length.sh</code> script</a> in each of the directories and output then into a file. For example:</p>

<pre><code>cd your-talks-day1
/path/to/get_lengths.sh &gt; ../lengths/day1.txt
</code></pre>

<p>Then combine the lengths of all days into a single file:</p>

<pre><code>cat ../lengths/*.txt &gt; ../talk_lengths.txt
</code></pre>

<p>Now you can create the final schedule:</p>

<pre><code>cd ..
python3 /path/to/list_recorded_talks.py schedule.json talk_lengths.txt
</code></pre>

<p>Here’s a sample <a href="https://gist.github.com/vmx/2f6499e8e0d2616098926f103dd86071">schedule from the FOSSGIS 2021</a>.</p>

<h3 id="miscellaneous-scripts">Miscellaneous Scripts</h3>

<h4 id="speaker-notification">Speaker notification</h4>

<p>The speakers didn’t get feedback whether their video was correctly uploaded/processed (other than seeing a successful upload in Seafile). A short time before the conference, we were sending out the latest information that speakers needs to know. We decided to take the chance to also add information whether their video upload was successful or not, so that they can contact us in case something with the upload didn’t go as they expected (there weren’t any issues :).</p>

<p>It is very similar to sending out the email with the upload links. You get the information about the speakers and talks in the same way. The only difference is we now also need the information whether the talk was pre-recorded or not. We get that from Seafile:</p>

<pre><code>curl --silent -X GET --header 'Authorization: Token &lt;seafile-token&gt;' 'https://seafile.example.org/api2/repos/&lt;repo-id&gt;/?p=/&lt;dir-with-talks&gt;&amp;t=d'|jq --raw-output '.[].name' &gt; prerecorded_talks.txt
</code></pre>

<p>The full script to create the emails can be found at <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/email_speaker_final/email_speaker_final.sh"><code>email_speaker_final.sh</code></a>. In order to post them to pretalx, you can use the <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/email_upload_links/email_to_pretalx.sh"><code>email_to_pretalx.sh</code></a> script and follow the description in the <a href="#creating-emails">creating emails</a> section.</p>

<h4 id="number-of-uploads">Number of uploads</h4>

<p>It could happen that people upload a new version of the talk. The current scripts won’t recognize that if a previous version was already reviewed. Hence, I manually checked the directories for the ones with more than one file in it. This can easily be done with a single curl command to the Seafile HTTP API:</p>

<pre><code>curl --silent -X GET --header 'Authorization: Token &lt;seafile-token&gt;' 'https://seafile.example.org/api2/repos/&lt;repo-id&gt;/dir/?p=/&lt;dir-with-talks&gt;&amp;t=f&amp;recursive=1'|jq --raw-output '.[].parent_dir'|sort|uniq -c|sort
</code></pre>

<p>The output is sorted by the number of files in that directory:</p>

<pre><code>  1 /talks_conference/ZVAZQQ
  1 /talks_conference/DXCNKG
  2 /talks_conference/H7TWNG
  2 /talks_conference/M1PR79
  2 /talks_conference/QW9KTH
  3 /talks_conference/VMM8MX
</code></pre>

<h4 id="normalize-volume-level">Normalize volume level</h4>

<p>If the volume of the talk was too low, it was normalized. I used <a href="https://github.com/slhck/ffmpeg-normalize">ffmpeg-normalize</a> for it:</p>

<pre><code>ffmpeg_normalize --audio-codec aac --progress talk.mkv
</code></pre>

<h3 id="conclusion">Conclusion</h3>

<p>Doing all this with scripts was a good idea. The less manual work the better. It also enabled me to process talks even during the conference in a semi-automated way. I created lots of small scripts and sometimes used just a subset of them, e.g. the <a href="https://github.com/vmx/conference-tools/blob/c06bd2bd8df64f992ffece37c6616732ee1a9f62/cut_to_schedule/copy_files.sh"><code>copy_files.sh</code> script</a>, or quickly modified them to deal with a special case. For example, all lightning talks of a single slot (2-4) were merged together into one video file. That file of course then isn’t associated with a single pretalx ID any more.</p>

<p>During the conference, the volume level of the pre-recorded talks was really different. I think for next time I’d like to do some automated audio level normalization after the people have uploaded the file. It should be done before reviewers have a look, so that they can report in case the normalization broke the audio.</p>

<p>The speakers were confused whether the upload really worked. Seafile doesn’t have an “upload now” button or so, it does it’s JavaScript magic once you’ve selected a file. That’s convenient, but was also confusing me, when I used it for the first time. And if you reload the page, you also won’t see that something was uploaded already. So perhaps it could also be automated that speakers get an email “we received your upload” or so.</p>

<p>Overall I’m really happy how the whole process went, there weren’t major failures like lost videos. I also haven’t heard any complaints from the people that needed to use any of the videos at any stage of the pipeline. I’d also like to thank all the speakers that uploaded a pre-recorded video, it really helped a lot running the FOSSGIS conference as smooth as it was.</p>

]]></content:encoded>
<wfw:commentRss>https://vmx.cx/cgi-bin/blog/index.cgi/video-uploads-for-an-online-conference%3A2021-06-12%3Aen%2Cconference%2Cgeo/feed/</wfw:commentRss>
</item>
<item>
<title>WebAssembly multi-value return in today's Rust without wasm-bindgen
</title>
<link>https://vmx.cx/cgi-bin/blog/index.cgi/webassembly-multi-value-return-in-todays-rust-without-wasm-bindgen%3A2021-01-29%3Aen%2CWASM%2CRust</link>
<comments>https://vmx.cx/cgi-bin/blog/index.cgi/webassembly-multi-value-return-in-todays-rust-without-wasm-bindgen%3A2021-01-29%3Aen%2CWASM%2CRust#comments</comments>
<pubDate>Fri, 29 Jan 2021 15:00:17 +0200</pubDate>
<dc:creator>Volker Mische</dc:creator>
<category>en</category>
<category>WASM</category>
<category>Rust</category>
<guid isPermaLink="false">https://vmx.cx/cgi-bin/blog/index.cgi/webassembly-multi-value-return-in-todays-rust-without-wasm-bindgen%3A2021-01-29%3Aen%2CWASM%2CRust/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[

<p>The goal was to run some <a href="https://webassembly.org/">WebAssembly</a> within different host languages. I needed a WASM file that is independent of the host language, hence I decided to code the <a href="https://en.wikipedia.org/wiki/Foreign_function_interface">FFI</a> manually, without using any tooling like <a href="https://rustwasm.github.io/docs/wasm-bindgen/">wasm-bindgen</a>, which is JavaScript specific. It needed a bit of custom tooling, but in the end I succeeded in having a WASM binary that has a multi-value return, generated with today's Rust compiler, without using wasm-bindgen annotations.</p>
<h3>Introduction</h3>
<p>In my case I wanted to pass some bytes into the WASM module, do some processing and returning some other bytes. I found all information I needed in this excellent <a href="https://radu-matei.com/blog/practical-guide-to-wasm-memory/">A practical guide to WebAssembly memory</a> from <a href="https://twitter.com/matei_radu">radu</a>. There he mentions the <a href="https://github.com/WebAssembly/multi-value">WebAssembly multi-value proposal</a> and links to a blog post from 2019 called <a href="https://hacks.mozilla.org/2019/11/multi-value-all-the-wasm/">Multi-Value All The Wasm!</a> which explains its implementation for the Rust ecosystem.</p>
<p>As it's from 2019 I just went ahead and thought I can use multi-value returns in Rust.</p>
<h3>The journey</h3>
<p>My function signature for the FFI looks like this:</p>
<pre><code class="language-rust">pub extern &quot;C&quot; fn decode(data_ptr: *const u8, data_len: usize) -&gt; (*const u8, usize) { … }
</code></pre>
<p>When I compiled it, I got this warning:</p>
<pre><code>warning: `extern` fn uses type `(*const u8, usize)`, which is not FFI-safe
 --&gt; src/lib.rs:2:67
  |
2 | pub extern &quot;C&quot; fn decode(data_ptr: *const u8, data_len: usize) -&gt; (*const u8, usize) {
  |                                                                   ^^^^^^^^^^^^^^^^^^ not FFI-safe
  |
  = note: `#[warn(improper_ctypes_definitions)]` on by default
  = help: consider using a struct instead
  = note: tuples have unspecified layout
</code></pre>
<p>Multi-value returns are certainly not meant for C APIs, but for WASM it might still work, I thought. Running <a href="https://github.com/WebAssembly/wabt">wasm2wat</a> shows:</p>
<pre><code class="language-wat">(module
  (type (;0;) (func (param i32 i32 i32)))
  (func $decode (type 0) (param i32 i32 i32)
…
</code></pre>
<p>This clearly isn't a multi-value return. It doesn't even have a return at all, it takes 3 parameters, instead of the 2 the function definition has. I found an issue called <a href="https://github.com/rust-lang/rust/issues/73755">Multi value Wasm compilation #73755</a> and was puzzled why it doesn't work. Is this a regression? Why did it work in that blog post from 2019? I gave the <a href="https://hacks.mozilla.org/2019/11/multi-value-all-the-wasm/">Multi-Value All The Wasm!</a> blog post another read, and it turns out it explains all this in detail (look at the <code>wasm-bindgen</code> section). Back then it wasn't supported by the Rust compiler directly, but by wasm-bindgen.</p>
<p>So perhaps I can just use the wasm-bindgen command line tool and transform my compiled WASM binary into a multi-value return one. There is a command-line flag called <code>WASM_BINDGEN_MULTI_VALUE=1</code> to enable that transformation. Sadly that doesn't really work as it needs some <a href="https://github.com/WebAssembly/interface-types/">interface-types</a> present in the WASM binary (which I don't have).</p>
<p>Thanks to open source, the blog post about the implementation of the transformation feature and some trial an error, I was able to extract the pieces I needed and created a tool called <a href="https://github.com/vmx/wasm-multi-value-reverse-polyfill/">wasm-multi-value-reverse-polyfill</a>. I didn't need to do any of the hard parts, just some wiring up. I was now able to transform my WASM binary into a multi-value return one simply by running:</p>
<pre><code class="language-console">$ multi-value-reverse-polyfill ./target/wasm32-unknown-unknown/release/wasm_multi_value_retun_in_rust.wasm 'decode i32 i32'
Make `decode` function return `[I32, I32]`.
</code></pre>
<p>The WAT disassembly now looks like that:</p>
<pre><code class="language-wat">  (type (;0;) (func (param i32 i32) (result i32 i32)))
  (type (;1;) (func (param i32 i32 i32)))
  (func $decode_multivalue_shim (type 0) (param i32 i32) (result i32 i32)
…
</code></pre>
<p>There you go. There is now a shim function that has the multi-value return, which calls the original method. I can now use my newly created WASM binary with WebAssembly runtimes that support multi-value returns (like <a href="https://wasmer.io/">Wasmer</a> or <a href="https:https://nodejs.org/">Node.js</a>).</p>
<h3>Conclusion</h3>
<p>With <a href="https://github.com/vmx/wasm-multi-value-reverse-polyfill/">wasm-multi-value-reverse-polyfill</a> I'm now able to create multi-value return functions with the current Rust compiler without depending on all the magic wasm-bindgen is doing.</p>
]]></content:encoded>
<wfw:commentRss>https://vmx.cx/cgi-bin/blog/index.cgi/webassembly-multi-value-return-in-todays-rust-without-wasm-bindgen%3A2021-01-29%3Aen%2CWASM%2CRust/feed/</wfw:commentRss>
</item>
<item>
<title>When npm link fails
</title>
<link>https://vmx.cx/cgi-bin/blog/index.cgi/when-npm-link-fails%3A2019-08-01%3Aen%2CJavaScript%2Cnpm</link>
<comments>https://vmx.cx/cgi-bin/blog/index.cgi/when-npm-link-fails%3A2019-08-01%3Aen%2CJavaScript%2Cnpm#comments</comments>
<pubDate>Thu, 01 Aug 2019 22:35:25 +0200</pubDate>
<dc:creator>Volker Mische</dc:creator>
<category>en</category>
<category>JavaScript</category>
<category>npm</category>
<guid isPermaLink="false">https://vmx.cx/cgi-bin/blog/index.cgi/when-npm-link-fails%3A2019-08-01%3Aen%2CJavaScript%2Cnpm/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[

<p>There are cases where linking local packages don't produce the same result as if you would've installed all packages from the registry. Here I'd like to tell the story about one of those real world cases and conclude with a solution to those problems.</p>
<h3>The problem</h3>
<p>When you do an <code>npm install</code> heavy module deduplication and hoisting, which doesn't always behave the same way in all cases. For example if you <code>npm link</code> a package, the resulting node_modules tree is different. This may lead to unexpected runtime errors.</p>
<p>It happened to me recently and I thought I use exactly this real world example to illustrate that problem and a possible solution to it.</p>
<h3>Real world example</h3>
<h4>Preparations</h4>
<p>Start with cloning the <a href="https://github.com/ipfs/js-ipfs-mfs/">js-ipfs-mfs</a> and <a href="https://github.com/ipfs/js-ipfs-unixfs-importer">js-ipfs-unixfs-importer</a> repository:</p>
<pre><code class="language-console">$ git clone https://github.com/ipfs/js-ipfs-mfs --branch v0.12.0 --depth 1
$ git clone https://github.com/ipfs/js-ipfs-unixfs-importer --branch v0.39.11 --depth 1
</code></pre>
<p>Our main module is js-ipfs-mfs and let's say you want to make local changes to js-ipfs-unix-importer, which is a direct dependency of js-ipfs-mfs.</p>
<p>First of all you of course make sure that currently the tests pass (we just run a subset, to get to the actual issue faster). I'm sorry that the installation takes so long and so much space, the dev dependencies are quite heavy.</p>
<pre><code class="language-console">$ cd js-ipfs-mfs
$ npm install
$ npx mocha test/write.spec.js
…
  53 passing (4s)
  1 pending
</code></pre>
<p>Ok, all tests passed.</p>
<h4>Reproducing the issue</h4>
<p>Before we even start modifying js-ipfs-unix-importer, we link it and check that the tests still pass.</p>
<pre><code class="language-console">$ cd js-ipfs-unixfs-importer
$ npm link
$ cd ../js-ipfs-mfs
$ npm link ipfs-unixfs-importer
$ npx mocha test/write.spec.js
…
  37 passing (2s)
  1 pending
  16 failing
…
</code></pre>
<p>Oh, no. The tests failed. But why? The reason is deep down in the code. The root cause is in the [hamt-sharding] module and it's not even a bug. It just <a href="https://github.com/ipfs-shipyard/js-hamt-sharding/blob/1e7e999f5718aad8bdeac37dd41f79e9904b54d4/src/bucket.jsL28-L30">checks if something is a <code>Bucket</code></a>:</p>
<pre><code class="language-JS">static isBucket (o) {
  return o instanceof Bucket
}
</code></pre>
<p><code>instanceof</code> only works if both instances we check on came from the exact same module. Let's see who is importing the hamt-sharding module:</p>
<pre><code class="language-console">$ npm ls hamt-sharding
ipfs-mfs@0.12.0 /home/vmx/misc/protocollabs/blog/when-npm-link-fails/js-ipfs-mfs
├── hamt-sharding@0.0.2
├─┬ ipfs-unixfs-exporter@0.37.7
│ └── hamt-sharding@0.0.2  deduped
└─┬ UNMET DEPENDENCY ipfs-unixfs-importer@0.39.11
  └── hamt-sharding@0.0.2  deduped

npm ERR! missing: ipfs-unixfs-importer@0.39.11, required by ipfs-mfs@0.12.0
</code></pre>
<p>Here we see that ipfs-mfs has a direct dependency on it, and an indirect dependency through ipfs-unixfs-exporter and ipfs-unixfs-importer.
All of them use the same version (0.0.2), hence it's <code>deduped</code> and the <code>instanceof</code> call should work.
But there's also an error about an <code>UNMET DEPENDENCY</code>, the ipfs-unixfs-importer module we linked to.</p>
<p>To make it clear what's happening inside Node.js. When you <code>require('hamt-sharding')</code> from the ipfs-mfs code base, it will load the module from the physical location <code>js-ipfs-mfs/node_modules/hamt-sharding</code>.
When you require it from ipfs-unixfs-importer it will be loaded from <code>js-ipfs-mfs/node_modules/ipfs-unixfs-importer/node_modules/hamt-sharding</code> resp. from <code>ipfs-unixfs-importer/node_modules/hamt-sharding</code>, as <code>js-ipfs-mfs/node_modules/ipfs-unixfs-importer</code> is just a symlink to a symlink to that directory.</p>
<p>When you do a normal installation without linking, you won't have this issue as hamt-sharding will be properly deduplicated and only loaded once from <code>js-ipfs-mfs/node_modules/hamt-sharding</code>.</p>
<h3>Possible workarounds that do not work</h3>
<p>Though you still like to change ipfs-unixfs-importer locally and test those changes with ipfs-mfs without breaking anything. I had several ideas on how to workaround this. I start with the ones that didn't work:</p>
<ol>
<li>Just delete the <code>js-ipfs-unixfs-importer/node_modules/hamt-sharding</code> directory. The module should still be found in the resolve paths of ipfs-mfs. No it doesn't. Tests fail because hamt-sharding can't be found.</li>
<li>Global linking runs an <code>npm install</code> when you run the initial <code>npm link</code>. What if we remove the <code>js-ipfs-unixfs-importer/node_modules</code> completely and symlink to the module manually. That also doesn't work, the hamt-sharding module also can't be found.</li>
<li>Install ipfs-unixfs-importer directly with a relative path (<code>npm install ../js-ipfs-unixfs-importer</code>). No, that doesn't work either, it will still have its own <code>node_modules/hamt-sharding</code>, it won't be properly deduplicated.</li>
</ol>
<p>There must be a way to make local changes to a module and testing them without publishing it each time. Luckily there really is.</p>
<h3>Working workaround</h3>
<p>I'd like to thank my colleague <a href="https://github.com/hugomrdias/">Hugo Dias</a> for this workaround that he has been using for a while already.</p>
<p>You can just replicate what a normal <code>npm install &lt;package&gt;</code> would be doing. You pack the module and then install that packed package. In our case that means:</p>
<pre><code class="language-console">$ cd js-ipfs-mfs
$ npm pack ../js-ipfs-unixfs-importer
…
ipfs-unixfs-importer-0.39.11.tgz
$ npm install ipfs-unixfs-importer-0.39.11.tgz
…
+ ipfs-unixfs-importer@0.39.11
added 59 packages from 76 contributors and updated 1 package in 31.698
</code></pre>
<p>Now all tests pass.</p>
<p>This is quite a manual process. Luckily Hugo created a module to automate exactly that workflow. It's called <a href="https://github.com/hugomrdias/connect-deps/">connect-deps</a>.</p>
<h3>Conclusion</h3>
<p>Sometimes linking packages doesn't create the same structure of modules and you need to use packing instead. To automate this you can use <a href="https://github.com/hugomrdias/connect-deps/">connect-deps</a>.</p>
]]></content:encoded>
<wfw:commentRss>https://vmx.cx/cgi-bin/blog/index.cgi/when-npm-link-fails%3A2019-08-01%3Aen%2CJavaScript%2Cnpm/feed/</wfw:commentRss>
</item>
<item>
<title>Show your own stripes
</title>
<link>https://vmx.cx/cgi-bin/blog/index.cgi/show-your-own-stripes%3A2019-06-20%3Aen%2Cclimatechange%2Ctutorial</link>
<comments>https://vmx.cx/cgi-bin/blog/index.cgi/show-your-own-stripes%3A2019-06-20%3Aen%2Cclimatechange%2Ctutorial#comments</comments>
<pubDate>Thu, 20 Jun 2019 22:35:25 +0200</pubDate>
<dc:creator>Volker Mische</dc:creator>
<category>en</category>
<category>climatechange</category>
<category>tutorial</category>
<guid isPermaLink="false">https://vmx.cx/cgi-bin/blog/index.cgi/show-your-own-stripes%3A2019-06-20%3Aen%2Cclimatechange%2Ctutorial/</guid>
<description><![CDATA[ <p>You want to create <a href="https://showyourstripes.info/">#ShowYourStripes</a> for the location you live in? Here's how.</p>
 [...]]]></description>
<content:encoded><![CDATA[
<p>You want to create <a href="https://showyourstripes.info/">#ShowYourStripes</a> for the location you live in? Here's how.</p>
<h3>Intro</h3>
<p><a href="/blog/2019-06-20/augsburg.png"><img src="/blog/2019-06-20/augsburg_small.png" alt="Timeline of yearly average temperatures in Augsburg, Germany" /></a></p>
<p>When I first saw <a href="https://showyourstripes.info/">#ShowYourStripes</a> I immediately felt in love (thanks <a href="https://twitter.com/StefanMuenz/status/1141264361601847300">Stefan Münz for tweeting about it</a>). I think it's a great and simple visualization by <a href="https://twitter.com/ed_hawkins">Ed Hawkins</a> of what we are currently facing when it comes to climate change. You don't need to scroll through long tables or figure out the axis on some diagram. You can simply see that there's something massively changing.</p>
<p>After playing around a bit with the cities available on the <a href="https://showyourstripes.info/">#ShowYourStripes website</a> I wanted to do the same for the city I live in, Augsburg, Germany. I looked at the website's source code first, in hope that it dynamically creates the data from some JSON or so. That isn't the case. I then searched Twitter, GitHub and the Web if I can find any related open source project. I wouldn't want to spend time figuring out the parameters that were used to create those. After all, I wanted mine to look exactly like those.</p>
<p>Luckily I found a <a href="https://twitter.com/hausfath/status/1140683014222929922">Tweet from Zeke Hausfather</a> saying that he could create those. I then <a href="https://twitter.com/vmx/status/1141301419624095745">asked him</a> if he could please release the source code. And just 7h later <a href="https://twitter.com/hausfath/status/1141408645776719872">he did</a>.</p>
<h3>Creating your own stripes</h3>
<p>Now it's time for a quick tutorial on how you can create your own #ShowYourStripes with that source code.</p>
<h4>Prerequisites</h4>
<p>I did those steps on a Debian system that had the most common tools installed (like <a href="https://python.org/">Python3</a>, or <a href="https://www.gnu.org/software/wget/">Wget</a>). I'm using <a href="https://pipenv.org/">Pipenv</a> for installing the required Python packages, but you can use any other package management tool for Python.</p>
<p>Let's get the data file with the global temperature values first. It's 200MB so it might take a while.</p>
<pre><code>wget http://berkeleyearth.lbl.gov/auto/Global/Gridded/Complete_TAVG_LatLong1.nc
</code></pre>
<p>Now retrieve the source code:</p>
<pre><code>$ wget https://raw.githubusercontent.com/hausfath/scrape_global_temps/master/City%20Warming%20Strips%20.ipynb -O showyourstripes.ipynb
</code></pre>
<p>In order to run the script, we need to get a few Python packages first:</p>
<pre><code>$ pipenv install matplotlib nbconvert netcdf4 numpy_indexed pandas
</code></pre>
<h3>Running the script</h3>
<p>The original script is a Jupyter Notebook, so we convert it to a plain Python script (you can ignore the warnings):</p>
<pre><code>$ pipenv run jupyter-nbconvert --to python showyourstripes.ipynb
</code></pre>
<p>Next we need to make some changes to the <code>showyourstripes.py</code> file so that it works on your machine and plots the stripes for your location. We work on the current directory, so you can comment out changing the directory:</p>
<pre><code>#os.chdir('/Users/hausfath/Desktop/Climate Science/GHCN Monthly/')
</code></pre>
<p>The other changes we need is the location the stripes should be plotted from. Here I use the values for Augsburg, Germany. Use your own values there. When I don't know the coordinates of my location, I usually check Wikipedia. In the top right corner <a href="https://en.wikipedia.org/wiki/Augsburg">of an article</a> you can find the coordinate of a place (if it has one attached). If you click on those you get to the <a href="https://tools.wmflabs.org/geohack/geohack.php?pagename=Augsburg&amp;params=48_22_N_10_54_E_type:city(292851)_region:DE-BY">GeoHack page of the article</a>. There on the top right you can find the coordinate in decimals in lat/lon order. In my case it's &quot;48.366667, 10.9&quot;.</p>
<pre><code>savename = 'augsburg'

lat = 48.366667
lon = 10.9
</code></pre>
<p>Now you're ready to run the script:</p>
<pre><code>pipenv run python showyourstripes.py
</code></pre>
<p>Now you should have an output file called <code>augsburg.png</code> in the same directory which contains the stripes.</p>
<h3>Conclusion</h3>
<p>Have fun creating your own #ShowYourStripes. Thanks again <a href="https://twitter.com/hausfath">Zeke Hausfather</a> for making and publishing the source code so quickly.</p>
]]></content:encoded>
<wfw:commentRss>https://vmx.cx/cgi-bin/blog/index.cgi/show-your-own-stripes%3A2019-06-20%3Aen%2Cclimatechange%2Ctutorial/feed/</wfw:commentRss>
</item>
<item>
<title>EU Urheberrechtsreform Nachlese
</title>
<link>https://vmx.cx/cgi-bin/blog/index.cgi/eu-urheberrechtsreform-nachlese%3A2019-04-23%3Ade%2CEU%2Cpolitics%2Ccopyright</link>
<comments>https://vmx.cx/cgi-bin/blog/index.cgi/eu-urheberrechtsreform-nachlese%3A2019-04-23%3Ade%2CEU%2Cpolitics%2Ccopyright#comments</comments>
<pubDate>Tue, 23 Apr 2019 22:35:25 +0200</pubDate>
<dc:creator>Volker Mische</dc:creator>
<category>de</category>
<category>EU</category>
<category>politics</category>
<category>copyright</category>
<guid isPermaLink="false">https://vmx.cx/cgi-bin/blog/index.cgi/eu-urheberrechtsreform-nachlese%3A2019-04-23%3Ade%2CEU%2Cpolitics%2Ccopyright/</guid>
<description><![CDATA[ <p>Die EU Urheberrechtsreform ist seit dem 15. April <a href="https://www.consilium.europa.eu/de/press/press-releases/2019/04/15/eu-adjusts-copyright-rules-to-the-digital-age/">endgültig beschlossen</a>. Leider konnten die strittigen Dinge wie Änderungen beim Leistungsschutzrecht oder <a href="https://www.bfdi.bund.de/DE/Infothek/Pressemitteilungen/2019/10_Uploadfilter.html;jsessionid=B4190157E6A16C7DB3E58255422229E5.2_cid329">drohende Uploadfilter</a> nicht verhindert werden.</p>
 [...]]]></description>
<content:encoded><![CDATA[
<p>Die EU Urheberrechtsreform ist seit dem 15. April <a href="https://www.consilium.europa.eu/de/press/press-releases/2019/04/15/eu-adjusts-copyright-rules-to-the-digital-age/">endgültig beschlossen</a>. Leider konnten die strittigen Dinge wie Änderungen beim Leistungsschutzrecht oder <a href="https://www.bfdi.bund.de/DE/Infothek/Pressemitteilungen/2019/10_Uploadfilter.html;jsessionid=B4190157E6A16C7DB3E58255422229E5.2_cid329">drohende Uploadfilter</a> nicht verhindert werden.</p>
<p>Zunächst ein bisschen Hintergrund zur Urheberrechtsreform. Die Reform sieht mehrere Änderungen vor, die durchaus nicht alle schlecht sind, einen guten Überblick zum Thema ist [dieser Blog-Eintrag von Julia Reda]. Noch vor der Abstimmung gab es einen, meines Erachtens, sehr guten <a href="https://www.mainpost.de/ueberregional/politik/brennpunkte/Gastbeitrag-Warum-Dorothee-Baer-die-EU-Urheberrechtsreform-ablehnt;art112,10202957">Gastbeitrag von Dorothee Bär bei der Main Post</a>, bei dem auf die negativen Auswirkungen der Reform eingegangen wird.</p>
<p>Darüber hinaus gab es auch die Warnung vom <a href="https://twitter.com/davidakaye">UN-Sonderberichterstatter zur Meinungsfreiheit David Kayne</a> davor, dass die Reform zur <a href="https://www.ohchr.org/EN/NewsEvents/Pages/DisplayNews.aspx?NewsID=24298&amp;LangID=E">Einschränkung der Meinungsfreiheit führen wird</a>.</p>
<p>Bereits einen Tag nach der Zustimmung des EU Parlaments am 26. März hatte der französische Kulturminister Franck Riester angekündigt, dass <a href="https://www.heise.de/newsticker/meldung/Upload-Filter-Bundesregierung-stellt-sich-hinter-die-EU-Urheberrechtsreform-4354724.html#nav_frankreich_will__1">Frankreich in Filtertechnologie investieren will</a>. Es wird also wohl trotz der <a href="http://data.consilium.europa.eu/doc/document/ST-7986-2019-ADD-1-REV-2/DE/pdf">Protokollnotiz Deutschlands</a> zu Uploadfiltern kommen.</p>
<p>Was mich bei der gesamten Debatte wirklich gestört hat, war die Unwissenheit vieler Beteiligter. Auch <a href="https://vmx.cx/cgi-bin/blog/index.cgi/why-i-am-against-the-eu-copyright-directive%3A2019-03-17%3Aen%2CEU%2Cpolitics%2Ccopyright">ich habe Fehler gemacht</a>, diesen aber umgehend korrigiert. Dabei ist es eben hilfreich auch die Argumente der Gegenseite zu hören. Besonders bei der <a href="http://www.europarl.europa.eu/streaming/de.html?event=20190326-0900-PLENARY&amp;start=2019-03-26T08:03:31Z&amp;end=2019-03-26T009:40:33Z&amp;language=de">Debatte im EU Parlament direkt vor der Abstimmung</a> (<a href="http://vod.europarl.europa.eu/download/nas/nasvod02/vod1303/2019/isma_splitV2/VODChapter_20190326_09003100_10404700_6d40c6169be6371f24126/VODChapter_20190326_09003100_10404700_6d40c6169be6371f24126_DE.mp4">direkt als Video</a>) wurden deutlich, wie viele Abgeordnete nicht wirklich verstanden haben, um was es genau geht, bzw. welche Folgen die Reform hat. Es gab sogar <a href="http://www.europarl.europa.eu/streaming/de.html?event=20190326-0900-PLENARY&amp;start=2019-03-26T09:22:05Z&amp;end=2019-03-26T009:22:17Z&amp;language=de">plumpe Angriffe</a>, die mit der eigentlichen Sache zu tun hatten. Es kam bei den Befürwortern wohl nicht an, dass auch die Gegner, wie ich, eine Urheberrechtsform wollen, es geht lediglich um deren Umsetzung. Der <a href="http://www.europarl.europa.eu/streaming/de.html?event=20190326-0900-PLENARY&amp;start=2019-03-26T08:24:39Z&amp;end=2019-03-26T08:32:25Z&amp;language=de">Redebeitrag von Julia Reda</a> war (wie so oft) hervorragend. Sie fasst die Faktenlage noch einmal kurz zusammen und beschreibt auch den Frust der Teilnehmer der <a href="https://www.tagesschau.de/inland/eu-urheberrechtsreform-protest-101.html">Massenproteste</a>. Zur möglichen Folge der Politikverdrossenheit gibt es auch einen <a href="https://www.tagesschau.de/wirtschaft/eu-richtlinie-urheberechtsreform-kommentar-101.html">sehr guten Kommentar auf tagesschau.de</a>.</p>
<p>Spannend ist auch noch die Frage, wer die eigentlichen Gewinner dieser Reform sind. Die Befürworter haben immer die Urheber als Gewinner der Reform ins Feld geführt. Allerdings handelte es dabei immer um Urheber die von Verwertungsgesellschaften vertreten werden. Es wurde dabei außer Acht gelassen, dass es gerade im Internetzeitalter eine Vielzahl von anderen Möglichkeiten gibt Urheber zu sein. Dazu gibt es zwei nette Geschichten, einmal der Versuch als <a href="https://twitter.com/pidy_unlimited/status/1105833785176834051">Privatperson für Fotos Vertreten zu werden</a>, das andere Mal als <a href="https://www.heise.de/newsticker/meldung/Kommentar-zur-EU-Urheberrechtsreform-Mit-zweierlei-Mass-4363951.html">Videoproducer auf YouTube</a>. Beides ist derzeit nicht möglich.</p>
<p>Ich hatte mich außerdem daran beteiligt bei den Brüsseler Büros der Abgeordneten anzurufen. Dabei war das Feedback sehr verschieden. Es reichte von einem freundlichen „ich werde dies so weitergeben“, über „die Abgeordnete stimmt wie ihre Kollegin, entgegen der Mehrheit ihrer Fraktion, bzw. der Bundesfraktion“ bis zu „es rufen so viele an, ich werde deshalb nicht mit Ihnen sprechen, die Abgeordnete wird sich aber eine fundierte Meinung bilden“ (im Endeffekt dann aber gar nicht abstimmen).</p>
<p>Zum Schluss möchte ich mich bei Allen bedanken die so hart dagegen gekämpft haben, Demos organisiert und natürlich auch den zahlreichen Teilnehmern.</p>
]]></content:encoded>
<wfw:commentRss>https://vmx.cx/cgi-bin/blog/index.cgi/eu-urheberrechtsreform-nachlese%3A2019-04-23%3Ade%2CEU%2Cpolitics%2Ccopyright/feed/</wfw:commentRss>
</item>
<item>
<title>Why I am against the EU Copyright Directive
</title>
<link>https://vmx.cx/cgi-bin/blog/index.cgi/why-i-am-against-the-eu-copyright-directive%3A2019-03-17%3Aen%2CEU%2Cpolitics%2Ccopyright</link>
<comments>https://vmx.cx/cgi-bin/blog/index.cgi/why-i-am-against-the-eu-copyright-directive%3A2019-03-17%3Aen%2CEU%2Cpolitics%2Ccopyright#comments</comments>
<pubDate>Sun, 17 Mar 2019 22:35:25 +0200</pubDate>
<dc:creator>Volker Mische</dc:creator>
<category>en</category>
<category>EU</category>
<category>politics</category>
<category>copyright</category>
<guid isPermaLink="false">https://vmx.cx/cgi-bin/blog/index.cgi/why-i-am-against-the-eu-copyright-directive%3A2019-03-17%3Aen%2CEU%2Cpolitics%2Ccopyright/</guid>
<description><![CDATA[ 
 [...]]]></description>
<content:encoded><![CDATA[

<p style="border:10px solid #f00;font-size:1.5em;padding:1em">
<strong>Update</strong> 2019-03-19: The argumentation below is <strong>wrong</strong>. A forum won't be considered a &quot;online content sharing service provider&quot; according to the definition of Article 2 (5) (page 51 of the <a href="https://juliareda.eu/wp-content/uploads/2019/02/Copyright_Final_compromise.pdf">full text of the final version</a>). I'm sorry for this misinformation. I keep the text below for reference so that others can see what I got wrong.
</p>

<p>There are many arguments against the EU Copyright Directive (more correct <a href="https://en.wikipedia.org/wiki/Directive_on_Copyright_in_the_Digital_Single_Market">Directive on Copyright in the Digital Single Market</a>) some I agree with, some I don't. Hence, here's my take on why I think that directive should be stopped. Short versions is: it strengthens the big platforms and weakens/destroys the small ones.</p>
<p>My hope is that this blog post will get more people interested in that topic and hopefully make you join the European wide protests on Saturday March 23rd 2019. If you want to join, there's an <a href="https://www.google.com/maps/d/viewer?mid=1tHaOiCgjION6hK0rrajIJyuHnG5FgBzH">interactive map of all known protests</a> created by the folks from <a href="https://www.stopacta2.org/en/">stopACTA2</a>.</p>
<h3>Intro</h3>
<p>It is confusing that platforms like <a href="https://www.youtube.com/saveyourinternet/">YouTube are against the directive</a>, it sounds like they have a lot to lose, hence they try everything they can against it. For me, this is normally a sign, that such a directive is exactly what it should do.</p>
<p>But it this case, it's not. YouTube will surely have its own reasons being against it. But what is more important for me is, that <em>if</em> the directive is approved by the European Parliament, the small platforms will almost have no chance to survive.</p>
<h3>Why small platforms will die</h3>
<p>There are exceptions in the directive for some platforms. You can find those in the <a href="https://juliareda.eu/wp-content/uploads/2019/02/Copyright_Final_compromise.pdf">full text of the final version</a> at paragraph (38b), page 36. But those exceptions won't help all smaller platforms. For example a discussion board which is older than 3 years and has advertising to cover the server costs wouldn't be excluded. They would be liable for every copyright infringement.</p>
<p>It could be a small as a profile picture, let's say yours is <a href="https://en.wikipedia.org/wiki/Luke_Skywalker">Luke Skywalker</a>. That platform could block custom profile pictures, but that still won't be enough. Someone could post some copyrighted text. But how would you make a discussion board without the users being able to post text? So the only way to not being liable would be to check for all infringements (how would you do that?), or close the platform.</p>
<h3>Outro</h3>
<p>I tried to keep it intentionally short and highlight the issue that matters to me most. Of course there's a lot more issues regarding the EU Copyright Directive, so if you want to know more, go to websites like <a href="https://savetheinternet.info/">savetheinternet.info</a>, <a href="https://www.stopacta2.org/en/">stopACTA2</a> or <a href="https://juliareda.eu/en/">Julia Reda's website</a> who is a Member of the European Parliament and puts lots of efforts in explaining and spreading the word on why the directive should be stopped (also <a href="https://twitter.com/senficon">follow her on Twitter</a>). Thanks a lot Julia for doing such an amazing work!</p>
]]></content:encoded>
<wfw:commentRss>https://vmx.cx/cgi-bin/blog/index.cgi/why-i-am-against-the-eu-copyright-directive%3A2019-03-17%3Aen%2CEU%2Cpolitics%2Ccopyright/feed/</wfw:commentRss>
</item>
</channel>
</rss>
