{"id":18376893,"url":"https://github.com/bbc/dvbcss-clocks","last_synced_at":"2026-04-25T21:34:22.214Z","repository":{"id":57217347,"uuid":"98913431","full_name":"bbc/dvbcss-clocks","owner":"bbc","description":"Javascript library implementing clock objects for modelling time. Useful in DVB CSS implementations.","archived":false,"fork":false,"pushed_at":"2017-12-12T14:12:28.000Z","size":69,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-04-09T05:43:11.035Z","etag":null,"topics":["companion","dvb","dvb-css","dvb-protocols","dvbcss","hbbtv2","javascript","media-synchronisation","node","nodejs","rd-project","rd-section-bcs","rd-stability-green","synchronisation","wall-clock"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bbc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-31T17:40:28.000Z","updated_at":"2023-11-15T08:43:14.000Z","dependencies_parsed_at":"2022-08-28T21:00:33.570Z","dependency_job_id":null,"html_url":"https://github.com/bbc/dvbcss-clocks","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/bbc/dvbcss-clocks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbc%2Fdvbcss-clocks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbc%2Fdvbcss-clocks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbc%2Fdvbcss-clocks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbc%2Fdvbcss-clocks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bbc","download_url":"https://codeload.github.com/bbc/dvbcss-clocks/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbc%2Fdvbcss-clocks/sbom","scorecard":{"id":227772,"data":{"date":"2025-08-11","repo":{"name":"github.com/bbc/dvbcss-clocks","commit":"c29d7a59d9871a6fad4b9025e8e1ff1b44864335"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}}]},"last_synced_at":"2025-08-17T04:09:17.269Z","repository_id":57217347,"created_at":"2025-08-17T04:09:17.269Z","updated_at":"2025-08-17T04:09:17.269Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32278249,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"ssl_error","status_checked_at":"2026-04-25T18:29:32.149Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["companion","dvb","dvb-css","dvb-protocols","dvbcss","hbbtv2","javascript","media-synchronisation","node","nodejs","rd-project","rd-section-bcs","rd-stability-green","synchronisation","wall-clock"],"created_at":"2024-11-06T00:25:19.536Z","updated_at":"2026-04-25T21:34:22.191Z","avatar_url":"https://github.com/bbc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JS objects to create hierarchies of clocks or timelines\n\n[![npm version](https://badge.fury.io/js/dvbcss-clocks.svg)](https://badge.fury.io/js/dvbcss-clocks)\n[![Build status](https://travis-ci.org/bbc/dvbcss-clocks.svg?branch=master)](https://travis-ci.org/bbc/dvbcss-clocks)\n[![API Doc](https://doclets.io/bbc/dvbcss-clocks/master.svg)](https://doclets.io/bbc/dvbcss-clocks/master)\n\n**dvbcss-clocks** is a Javascript library of classes for representing clocks\nand timelines and their relationships to each other. It can be used in event\ndriven real-time applications to drive and track the progress of time, such\nas synchronised companion screen applications based on \n[DVB CSS](http://www.etsi.org/standards-search?search=103+286\u0026page=1\u0026title=1\u0026keywords=1\u0026ed=1\u0026sortby=1)\nor [HbbTV 2](http://hbbtv.org/resource-library/). \n\nThis library is very similar to the clock objects in [pydvbcss](https://github.com/bbc/pydvbcss) and uses the same concepts and\noverall model. There is a direct 1-to-1 correspondence of most classes and methods\nbetween the two.\n\n\u003cimg src=\"https://2immerse.eu/wp-content/uploads/2016/04/2-IMM_150x50.png\" align=\"left\"/\u003e\u003cem\u003eThis project was originally developed as part of the \u003ca href=\"https://2immerse.eu/\"\u003e2-IMMERSE\u003c/a\u003e project, co-funded by the European Commission’s \u003ca hef=\"http://ec.europa.eu/programmes/horizon2020/\"\u003eHorizon 2020\u003c/a\u003e Research Programme\u003c/em\u003e\n\n\n## Getting started\n\n### Use in your own project\n\nInstall via npm:\n\n    $ npm install --save dvbcss-clocks\n\nOr download or clone this repository and build:\n\n    $ cd dvbcss-clocks \n    $ npm install\n    \n\n### Documentation\n\nThe full docs for the library [can be read online here](https://doclets.io/bbc/dvbcss-clocks/master/overview).\n\nTo build the docs yourself:\n\n    $ grunt jsdoc\n\n### Unit tests\n\nUnit tests are written using the jasmine unit test framework.\n\n    $ grunt test\n\n## Quick overview\n\nIn this library, objects represent clocks that can be chained together into a\nhierarchy and used to represent how one sense of time relates to another - e.g.\nhow a timeline for media playback relates to real world time.\n\nFirst we import the modules:\n\n    var CLOCKS = require(\"dvbcss-clocks\")\n    var DateNowClock    = CLOCKS.DateNowClock;\n    var Correlation     = CLOCKS.Correlation;\n    var CorrelatedClock = CLOCKS.CorrelatedClock;\n\nA `DateNowClock` can be used as the root of the hierarchy and is a simple wrapper\naround system time derived from `Date.now()`.\n\n    var rootClock = new DateNowClock({tickRate:1000, maxFreqErrorPpm:50});\n\nWe can query the time position of this clock at any time:\n\n    console.log(rootClock.now())\n\nA hierarchy can then be built up using `CorrelatedClock` objects where a `correlation`\ndescribes the relationship between that clock and its parent. For example, we\nwill create a \"wall clock\" that is derived from the system clock:\n\n    var corr = new Correlation(5000, 0)\n    var wallClock = new CorrelatedClock(rootClock, {\n        tickRate: 50,\n        correlation: corr\n    })\n\nThis units for this clock are 50 ticks/second, and the correlation\nmeans that when its parent clock (`rootClock`) is at time position 5000,\nthen this clock should be at time position 0.\n\nIf we query the position of this clock, we'll see that it is calculated from\nits parent by extrapolating from that point of correlation and converting to\nthe different tick rate units. For example, executing this command several times:\n\n    console.log(rootClock.now(), wallClock.now())\n\nCan give results like this:\n\n    \u003e 5000, 0\n    \u003e 5200, 10\n    \u003e 5215, 10.75\n    \nNext we'll add another clock into the chain that is derived from the \"wall clock\"\nand we will imagine it represents the timeline of a video player that is due to\nstart playing from time zero right now:\n\n    var videoTimeline = new CorrelatedClock(wallClock, {\n        tickRate: 25,\n        correlation: new Correlation(wallClock.now(), 0)\n    })\n    \nLets listen for events:\n\n    videoTimeline.on(\"change\", function() { console.log(\"Video timeline is notifying of a change\")});\n    videoTimeline.on(\"available\", function() { console.log(\"Video timeline has become available\")});\n    videoTimeline.on(\"unavailable\", function() { console.log(\"Video timeline has become unavailable\")});\n\nLets change the wall clock correlation. This will generate a `change` event on all clocks\nthat are descendents (as well as itself):\n\n    # reset wall clock to zero now\n\n    wallClock.correlation = new Correlation(rootClock.now(), 0);\n    console.log(\"Wall clock time = \"+wallClock.now());\n\nLets also make some other changes (this will generate a `change` event and availability change events):\n    \n    wallClock.speed = 2.0   // double the speed!\n\n    wallClock.availabilityFlag = false;\n    wallClock.availabilityFlag = true;\n    \nLets schedule some timer callbacks:\n\n    # schedule a timer callback so we know to stop the video at frame 500\n    videoTimeline.setAtTime(function() { console.log(\"Time to stop video\")}, 500);\n    \nEven if we make more changes to correlations this timer callback will only fire\nwhen the video timeline reaches (or jumps past) time position 500.\n\nThere are many other methods not covered here. See the documentation.\n\nClocks can be built up into arbitrarily complex hierarchies and these can be reconfigured dynamically. There\nare helper methods to provide easy conversion of time values between clocks. There are also ways to annotate\nclocks with quantified uncertainty bounds (dispersions) and have these tracked by their descendants.\n\n\n## Licence and Authors\n\nAll code and documentation is licensed by the original author and contributors under the Apache License v2.0:\n\n* [British Broadcasting Corporation](http://www.bbc.co.uk/rd) (original author)\n* [British Telecommunications (BT) PLC](http://www.bt.com/)\n\nSee AUTHORS file for a full list of individuals and organisations that have\ncontributed to this code.\n.\n\n## Contributing\n\nIf you wish to contribute to this project, please get in touch with the authors.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbbc%2Fdvbcss-clocks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbbc%2Fdvbcss-clocks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbbc%2Fdvbcss-clocks/lists"}