{"id":954,"date":"2014-12-02T01:13:14","date_gmt":"2014-12-01T14:13:14","guid":{"rendered":"http:\/\/noraisin.net\/diary\/?p=954"},"modified":"2014-12-02T01:13:14","modified_gmt":"2014-12-01T14:13:14","slug":"network-clock-examples","status":"publish","type":"post","link":"https:\/\/noraisin.net\/diary\/?p=954","title":{"rendered":"Network clock examples"},"content":{"rendered":"<p>Way back in 2006, <a title=\"Andy Wingo\" href=\"http:\/\/wingolog.org\/\">Andy Wingo<\/a> wrote some small scripts for GStreamer 0.10 to demonstrate what was (back then) a fairly new feature in GStreamer &#8211; the ability to share a clock across the network and use it to synchronise playback of content across different machines.<\/p>\n<p>Since GStreamer 1.x has been out for over 2 years, and we get a lot of questions about how to use the network clock functionality, it&#8217;s a good time for an update. I&#8217;ve ported the simple examples for API changes and to use the gobject-introspection based Python bindings and put them up on my server.<\/p>\n<p>To give it a try, fetch <a href=\"http:\/\/noraisin.net\/gst\/play-master.py\">play-master.py<\/a> and <a href=\"http:\/\/noraisin.net\/gst\/play-slave.py\">play-slave.py<\/a> onto 2 or more computers with GStreamer 1 installed. You need a media file accessible via some URI to all machines, so they have something to play.<\/p>\n<p>Then, on one machine run play-master.py, passing a URI for it to play and a port to publish the clock on:<\/p>\n<blockquote><p>.\/play-master.py http:\/\/server\/path\/to\/file 8554<\/p><\/blockquote>\n<p>The script will print out a command line like so:<\/p>\n<blockquote><p>Start slave as: python .\/play-slave.py\u00a0http:\/\/server\/path\/to\/file [IP] 8554 1071152650838999<\/p><\/blockquote>\n<p>On another machine(s), run the printed command, substituting the IP address of the machine running the master script.<\/p>\n<p>After a moment or two, the slaved machine should start playing the file in synch with the master:<\/p>\n<p><a href=\"http:\/\/noraisin.net\/diary\/wp-content\/uploads\/2014\/12\/20141202_004910.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-955 size-medium\" src=\"http:\/\/noraisin.net\/diary\/wp-content\/uploads\/2014\/12\/20141202_004910-e1417442897206-300x296.jpg\" alt=\"Network Synchronised Playback\" width=\"300\" height=\"296\" srcset=\"https:\/\/noraisin.net\/diary\/wp-content\/uploads\/2014\/12\/20141202_004910-e1417442897206-300x296.jpg 300w, https:\/\/noraisin.net\/diary\/wp-content\/uploads\/2014\/12\/20141202_004910-e1417442897206-1024x1013.jpg 1024w\" sizes=\"auto, (max-width: 300px) 85vw, 300px\" \/><\/a><\/p>\n<p>If they&#8217;re not in sync, check that you have the port you chose open for UDP traffic so the clock synchronisation packets can be transferred.<\/p>\n<p>This basic technique is the core of my <a title=\"Aurena\" href=\"https:\/\/github.com\/thaytan\/aurena\">Aurena<\/a> home media player system, which builds on top of the network clock mechanism to provide file serving and a simple shuffle playlist.<\/p>\n<p>For anyone still interested in GStreamer 0.10 &#8211; Andy&#8217;s old scripts can be found on his server: <a href=\"http:\/\/wingolog.org\/pub\/play-master.py\">play-master.py<\/a> and <a href=\"http:\/\/wingolog.org\/pub\/play-slave.py\">play-slave.py<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Way back in 2006, Andy Wingo wrote some small scripts for GStreamer 0.10 to demonstrate what was (back then) a fairly new feature in GStreamer &#8211; the ability to share a clock across the network and use it to synchronise playback of content across different machines. Since GStreamer 1.x has been out for over 2 &hellip; <a href=\"https:\/\/noraisin.net\/diary\/?p=954\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Network clock examples&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-954","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/noraisin.net\/diary\/index.php?rest_route=\/wp\/v2\/posts\/954","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/noraisin.net\/diary\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/noraisin.net\/diary\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/noraisin.net\/diary\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/noraisin.net\/diary\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=954"}],"version-history":[{"count":1,"href":"https:\/\/noraisin.net\/diary\/index.php?rest_route=\/wp\/v2\/posts\/954\/revisions"}],"predecessor-version":[{"id":956,"href":"https:\/\/noraisin.net\/diary\/index.php?rest_route=\/wp\/v2\/posts\/954\/revisions\/956"}],"wp:attachment":[{"href":"https:\/\/noraisin.net\/diary\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=954"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/noraisin.net\/diary\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=954"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/noraisin.net\/diary\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=954"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}