diff --git a/.lock b/.lock new file mode 100644 index 0000000..e69de29 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..6c49820 --- /dev/null +++ b/404.html @@ -0,0 +1,200 @@ + + + + + + Page not found - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

Document not found (404)

+

This URL is invalid, sorry. Please use the navigation bar or search to continue.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/FontAwesome/css/font-awesome.css b/FontAwesome/css/font-awesome.css new file mode 100644 index 0000000..540440c --- /dev/null +++ b/FontAwesome/css/font-awesome.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/FontAwesome/fonts/FontAwesome.ttf b/FontAwesome/fonts/FontAwesome.ttf new file mode 100644 index 0000000..35acda2 Binary files /dev/null and b/FontAwesome/fonts/FontAwesome.ttf differ diff --git a/FontAwesome/fonts/fontawesome-webfont.eot b/FontAwesome/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..e9f60ca Binary files /dev/null and b/FontAwesome/fonts/fontawesome-webfont.eot differ diff --git a/FontAwesome/fonts/fontawesome-webfont.svg b/FontAwesome/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..855c845 --- /dev/null +++ b/FontAwesome/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FontAwesome/fonts/fontawesome-webfont.ttf b/FontAwesome/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..35acda2 Binary files /dev/null and b/FontAwesome/fonts/fontawesome-webfont.ttf differ diff --git a/FontAwesome/fonts/fontawesome-webfont.woff b/FontAwesome/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..400014a Binary files /dev/null and b/FontAwesome/fonts/fontawesome-webfont.woff differ diff --git a/FontAwesome/fonts/fontawesome-webfont.woff2 b/FontAwesome/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000..4d13fc6 Binary files /dev/null and b/FontAwesome/fonts/fontawesome-webfont.woff2 differ diff --git a/ayu-highlight.css b/ayu-highlight.css new file mode 100644 index 0000000..32c9432 --- /dev/null +++ b/ayu-highlight.css @@ -0,0 +1,78 @@ +/* +Based off of the Ayu theme +Original by Dempfi (https://github.com/dempfi/ayu) +*/ + +.hljs { + display: block; + overflow-x: auto; + background: #191f26; + color: #e6e1cf; +} + +.hljs-comment, +.hljs-quote { + color: #5c6773; + font-style: italic; +} + +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-attr, +.hljs-regexp, +.hljs-link, +.hljs-selector-id, +.hljs-selector-class { + color: #ff7733; +} + +.hljs-number, +.hljs-meta, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #ffee99; +} + +.hljs-string, +.hljs-bullet { + color: #b8cc52; +} + +.hljs-title, +.hljs-built_in, +.hljs-section { + color: #ffb454; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-symbol { + color: #ff7733; +} + +.hljs-name { + color: #36a3d9; +} + +.hljs-tag { + color: #00568d; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-addition { + color: #91b362; +} + +.hljs-deletion { + color: #d96c75; +} diff --git a/book.js b/book.js new file mode 100644 index 0000000..178f1e9 --- /dev/null +++ b/book.js @@ -0,0 +1,690 @@ +"use strict"; + +// Fix back button cache problem +window.onunload = function () { }; + +// Global variable, shared between modules +function playground_text(playground, hidden = true) { + let code_block = playground.querySelector("code"); + + if (window.ace && code_block.classList.contains("editable")) { + let editor = window.ace.edit(code_block); + return editor.getValue(); + } else if (hidden) { + return code_block.textContent; + } else { + return code_block.innerText; + } +} + +(function codeSnippets() { + function fetch_with_timeout(url, options, timeout = 6000) { + return Promise.race([ + fetch(url, options), + new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout)) + ]); + } + + var playgrounds = Array.from(document.querySelectorAll(".playground")); + if (playgrounds.length > 0) { + fetch_with_timeout("https://play.rust-lang.org/meta/crates", { + headers: { + 'Content-Type': "application/json", + }, + method: 'POST', + mode: 'cors', + }) + .then(response => response.json()) + .then(response => { + // get list of crates available in the rust playground + let playground_crates = response.crates.map(item => item["id"]); + playgrounds.forEach(block => handle_crate_list_update(block, playground_crates)); + }); + } + + function handle_crate_list_update(playground_block, playground_crates) { + // update the play buttons after receiving the response + update_play_button(playground_block, playground_crates); + + // and install on change listener to dynamically update ACE editors + if (window.ace) { + let code_block = playground_block.querySelector("code"); + if (code_block.classList.contains("editable")) { + let editor = window.ace.edit(code_block); + editor.addEventListener("change", function (e) { + update_play_button(playground_block, playground_crates); + }); + // add Ctrl-Enter command to execute rust code + editor.commands.addCommand({ + name: "run", + bindKey: { + win: "Ctrl-Enter", + mac: "Ctrl-Enter" + }, + exec: _editor => run_rust_code(playground_block) + }); + } + } + } + + // updates the visibility of play button based on `no_run` class and + // used crates vs ones available on https://play.rust-lang.org + function update_play_button(pre_block, playground_crates) { + var play_button = pre_block.querySelector(".play-button"); + + // skip if code is `no_run` + if (pre_block.querySelector('code').classList.contains("no_run")) { + play_button.classList.add("hidden"); + return; + } + + // get list of `extern crate`'s from snippet + var txt = playground_text(pre_block); + var re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g; + var snippet_crates = []; + var item; + while (item = re.exec(txt)) { + snippet_crates.push(item[1]); + } + + // check if all used crates are available on play.rust-lang.org + var all_available = snippet_crates.every(function (elem) { + return playground_crates.indexOf(elem) > -1; + }); + + if (all_available) { + play_button.classList.remove("hidden"); + } else { + play_button.classList.add("hidden"); + } + } + + function run_rust_code(code_block) { + var result_block = code_block.querySelector(".result"); + if (!result_block) { + result_block = document.createElement('code'); + result_block.className = 'result hljs language-bash'; + + code_block.append(result_block); + } + + let text = playground_text(code_block); + let classes = code_block.querySelector('code').classList; + let edition = "2015"; + if(classes.contains("edition2018")) { + edition = "2018"; + } else if(classes.contains("edition2021")) { + edition = "2021"; + } + var params = { + version: "stable", + optimize: "0", + code: text, + edition: edition + }; + + if (text.indexOf("#![feature") !== -1) { + params.version = "nightly"; + } + + result_block.innerText = "Running..."; + + fetch_with_timeout("https://play.rust-lang.org/evaluate.json", { + headers: { + 'Content-Type': "application/json", + }, + method: 'POST', + mode: 'cors', + body: JSON.stringify(params) + }) + .then(response => response.json()) + .then(response => { + if (response.result.trim() === '') { + result_block.innerText = "No output"; + result_block.classList.add("result-no-output"); + } else { + result_block.innerText = response.result; + result_block.classList.remove("result-no-output"); + } + }) + .catch(error => result_block.innerText = "Playground Communication: " + error.message); + } + + // Syntax highlighting Configuration + hljs.configure({ + tabReplace: ' ', // 4 spaces + languages: [], // Languages used for auto-detection + }); + + let code_nodes = Array + .from(document.querySelectorAll('code')) + // Don't highlight `inline code` blocks in headers. + .filter(function (node) {return !node.parentElement.classList.contains("header"); }); + + if (window.ace) { + // language-rust class needs to be removed for editable + // blocks or highlightjs will capture events + code_nodes + .filter(function (node) {return node.classList.contains("editable"); }) + .forEach(function (block) { block.classList.remove('language-rust'); }); + + code_nodes + .filter(function (node) {return !node.classList.contains("editable"); }) + .forEach(function (block) { hljs.highlightBlock(block); }); + } else { + code_nodes.forEach(function (block) { hljs.highlightBlock(block); }); + } + + // Adding the hljs class gives code blocks the color css + // even if highlighting doesn't apply + code_nodes.forEach(function (block) { block.classList.add('hljs'); }); + + Array.from(document.querySelectorAll("code.hljs")).forEach(function (block) { + + var lines = Array.from(block.querySelectorAll('.boring')); + // If no lines were hidden, return + if (!lines.length) { return; } + block.classList.add("hide-boring"); + + var buttons = document.createElement('div'); + buttons.className = 'buttons'; + buttons.innerHTML = ""; + + // add expand button + var pre_block = block.parentNode; + pre_block.insertBefore(buttons, pre_block.firstChild); + + pre_block.querySelector('.buttons').addEventListener('click', function (e) { + if (e.target.classList.contains('fa-eye')) { + e.target.classList.remove('fa-eye'); + e.target.classList.add('fa-eye-slash'); + e.target.title = 'Hide lines'; + e.target.setAttribute('aria-label', e.target.title); + + block.classList.remove('hide-boring'); + } else if (e.target.classList.contains('fa-eye-slash')) { + e.target.classList.remove('fa-eye-slash'); + e.target.classList.add('fa-eye'); + e.target.title = 'Show hidden lines'; + e.target.setAttribute('aria-label', e.target.title); + + block.classList.add('hide-boring'); + } + }); + }); + + if (window.playground_copyable) { + Array.from(document.querySelectorAll('pre code')).forEach(function (block) { + var pre_block = block.parentNode; + if (!pre_block.classList.contains('playground')) { + var buttons = pre_block.querySelector(".buttons"); + if (!buttons) { + buttons = document.createElement('div'); + buttons.className = 'buttons'; + pre_block.insertBefore(buttons, pre_block.firstChild); + } + + var clipButton = document.createElement('button'); + clipButton.className = 'clip-button'; + clipButton.title = 'Copy to clipboard'; + clipButton.setAttribute('aria-label', clipButton.title); + clipButton.innerHTML = ''; + + buttons.insertBefore(clipButton, buttons.firstChild); + } + }); + } + + // Process playground code blocks + Array.from(document.querySelectorAll(".playground")).forEach(function (pre_block) { + // Add play button + var buttons = pre_block.querySelector(".buttons"); + if (!buttons) { + buttons = document.createElement('div'); + buttons.className = 'buttons'; + pre_block.insertBefore(buttons, pre_block.firstChild); + } + + var runCodeButton = document.createElement('button'); + runCodeButton.className = 'fa fa-play play-button'; + runCodeButton.hidden = true; + runCodeButton.title = 'Run this code'; + runCodeButton.setAttribute('aria-label', runCodeButton.title); + + buttons.insertBefore(runCodeButton, buttons.firstChild); + runCodeButton.addEventListener('click', function (e) { + run_rust_code(pre_block); + }); + + if (window.playground_copyable) { + var copyCodeClipboardButton = document.createElement('button'); + copyCodeClipboardButton.className = 'clip-button'; + copyCodeClipboardButton.innerHTML = ''; + copyCodeClipboardButton.title = 'Copy to clipboard'; + copyCodeClipboardButton.setAttribute('aria-label', copyCodeClipboardButton.title); + + buttons.insertBefore(copyCodeClipboardButton, buttons.firstChild); + } + + let code_block = pre_block.querySelector("code"); + if (window.ace && code_block.classList.contains("editable")) { + var undoChangesButton = document.createElement('button'); + undoChangesButton.className = 'fa fa-history reset-button'; + undoChangesButton.title = 'Undo changes'; + undoChangesButton.setAttribute('aria-label', undoChangesButton.title); + + buttons.insertBefore(undoChangesButton, buttons.firstChild); + + undoChangesButton.addEventListener('click', function () { + let editor = window.ace.edit(code_block); + editor.setValue(editor.originalCode); + editor.clearSelection(); + }); + } + }); +})(); + +(function themes() { + var html = document.querySelector('html'); + var themeToggleButton = document.getElementById('theme-toggle'); + var themePopup = document.getElementById('theme-list'); + var themeColorMetaTag = document.querySelector('meta[name="theme-color"]'); + var themeIds = []; + themePopup.querySelectorAll('button.theme').forEach(function (el) { + themeIds.push(el.id); + }); + var stylesheets = { + ayuHighlight: document.querySelector("[href$='ayu-highlight.css']"), + tomorrowNight: document.querySelector("[href$='tomorrow-night.css']"), + highlight: document.querySelector("[href$='highlight.css']"), + }; + + function showThemes() { + themePopup.style.display = 'block'; + themeToggleButton.setAttribute('aria-expanded', true); + themePopup.querySelector("button#" + get_theme()).focus(); + } + + function updateThemeSelected() { + themePopup.querySelectorAll('.theme-selected').forEach(function (el) { + el.classList.remove('theme-selected'); + }); + themePopup.querySelector("button#" + get_theme()).classList.add('theme-selected'); + } + + function hideThemes() { + themePopup.style.display = 'none'; + themeToggleButton.setAttribute('aria-expanded', false); + themeToggleButton.focus(); + } + + function get_theme() { + var theme; + try { theme = localStorage.getItem('mdbook-theme'); } catch (e) { } + if (theme === null || theme === undefined || !themeIds.includes(theme)) { + return default_theme; + } else { + return theme; + } + } + + function set_theme(theme, store = true) { + let ace_theme; + + if (theme == 'coal' || theme == 'navy') { + stylesheets.ayuHighlight.disabled = true; + stylesheets.tomorrowNight.disabled = false; + stylesheets.highlight.disabled = true; + + ace_theme = "ace/theme/tomorrow_night"; + } else if (theme == 'ayu') { + stylesheets.ayuHighlight.disabled = false; + stylesheets.tomorrowNight.disabled = true; + stylesheets.highlight.disabled = true; + ace_theme = "ace/theme/tomorrow_night"; + } else { + stylesheets.ayuHighlight.disabled = true; + stylesheets.tomorrowNight.disabled = true; + stylesheets.highlight.disabled = false; + ace_theme = "ace/theme/dawn"; + } + + setTimeout(function () { + themeColorMetaTag.content = getComputedStyle(document.documentElement).backgroundColor; + }, 1); + + if (window.ace && window.editors) { + window.editors.forEach(function (editor) { + editor.setTheme(ace_theme); + }); + } + + var previousTheme = get_theme(); + + if (store) { + try { localStorage.setItem('mdbook-theme', theme); } catch (e) { } + } + + html.classList.remove(previousTheme); + html.classList.add(theme); + updateThemeSelected(); + } + + // Set theme + var theme = get_theme(); + + set_theme(theme, false); + + themeToggleButton.addEventListener('click', function () { + if (themePopup.style.display === 'block') { + hideThemes(); + } else { + showThemes(); + } + }); + + themePopup.addEventListener('click', function (e) { + var theme; + if (e.target.className === "theme") { + theme = e.target.id; + } else if (e.target.parentElement.className === "theme") { + theme = e.target.parentElement.id; + } else { + return; + } + set_theme(theme); + }); + + themePopup.addEventListener('focusout', function(e) { + // e.relatedTarget is null in Safari and Firefox on macOS (see workaround below) + if (!!e.relatedTarget && !themeToggleButton.contains(e.relatedTarget) && !themePopup.contains(e.relatedTarget)) { + hideThemes(); + } + }); + + // Should not be needed, but it works around an issue on macOS & iOS: https://github.com/rust-lang/mdBook/issues/628 + document.addEventListener('click', function(e) { + if (themePopup.style.display === 'block' && !themeToggleButton.contains(e.target) && !themePopup.contains(e.target)) { + hideThemes(); + } + }); + + document.addEventListener('keydown', function (e) { + if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; } + if (!themePopup.contains(e.target)) { return; } + + switch (e.key) { + case 'Escape': + e.preventDefault(); + hideThemes(); + break; + case 'ArrowUp': + e.preventDefault(); + var li = document.activeElement.parentElement; + if (li && li.previousElementSibling) { + li.previousElementSibling.querySelector('button').focus(); + } + break; + case 'ArrowDown': + e.preventDefault(); + var li = document.activeElement.parentElement; + if (li && li.nextElementSibling) { + li.nextElementSibling.querySelector('button').focus(); + } + break; + case 'Home': + e.preventDefault(); + themePopup.querySelector('li:first-child button').focus(); + break; + case 'End': + e.preventDefault(); + themePopup.querySelector('li:last-child button').focus(); + break; + } + }); +})(); + +(function sidebar() { + var body = document.querySelector("body"); + var sidebar = document.getElementById("sidebar"); + var sidebarLinks = document.querySelectorAll('#sidebar a'); + var sidebarToggleButton = document.getElementById("sidebar-toggle"); + var sidebarResizeHandle = document.getElementById("sidebar-resize-handle"); + var firstContact = null; + + function showSidebar() { + body.classList.remove('sidebar-hidden') + body.classList.add('sidebar-visible'); + Array.from(sidebarLinks).forEach(function (link) { + link.setAttribute('tabIndex', 0); + }); + sidebarToggleButton.setAttribute('aria-expanded', true); + sidebar.setAttribute('aria-hidden', false); + try { localStorage.setItem('mdbook-sidebar', 'visible'); } catch (e) { } + } + + function hideSidebar() { + body.classList.remove('sidebar-visible') + body.classList.add('sidebar-hidden'); + Array.from(sidebarLinks).forEach(function (link) { + link.setAttribute('tabIndex', -1); + }); + sidebarToggleButton.setAttribute('aria-expanded', false); + sidebar.setAttribute('aria-hidden', true); + try { localStorage.setItem('mdbook-sidebar', 'hidden'); } catch (e) { } + } + + // Toggle sidebar + sidebarToggleButton.addEventListener('click', function sidebarToggle() { + if (body.classList.contains("sidebar-hidden")) { + var current_width = parseInt( + document.documentElement.style.getPropertyValue('--sidebar-width'), 10); + if (current_width < 150) { + document.documentElement.style.setProperty('--sidebar-width', '150px'); + } + showSidebar(); + } else if (body.classList.contains("sidebar-visible")) { + hideSidebar(); + } else { + if (getComputedStyle(sidebar)['transform'] === 'none') { + hideSidebar(); + } else { + showSidebar(); + } + } + }); + + sidebarResizeHandle.addEventListener('mousedown', initResize, false); + + function initResize(e) { + window.addEventListener('mousemove', resize, false); + window.addEventListener('mouseup', stopResize, false); + body.classList.add('sidebar-resizing'); + } + function resize(e) { + var pos = (e.clientX - sidebar.offsetLeft); + if (pos < 20) { + hideSidebar(); + } else { + if (body.classList.contains("sidebar-hidden")) { + showSidebar(); + } + pos = Math.min(pos, window.innerWidth - 100); + document.documentElement.style.setProperty('--sidebar-width', pos + 'px'); + } + } + //on mouseup remove windows functions mousemove & mouseup + function stopResize(e) { + body.classList.remove('sidebar-resizing'); + window.removeEventListener('mousemove', resize, false); + window.removeEventListener('mouseup', stopResize, false); + } + + document.addEventListener('touchstart', function (e) { + firstContact = { + x: e.touches[0].clientX, + time: Date.now() + }; + }, { passive: true }); + + document.addEventListener('touchmove', function (e) { + if (!firstContact) + return; + + var curX = e.touches[0].clientX; + var xDiff = curX - firstContact.x, + tDiff = Date.now() - firstContact.time; + + if (tDiff < 250 && Math.abs(xDiff) >= 150) { + if (xDiff >= 0 && firstContact.x < Math.min(document.body.clientWidth * 0.25, 300)) + showSidebar(); + else if (xDiff < 0 && curX < 300) + hideSidebar(); + + firstContact = null; + } + }, { passive: true }); +})(); + +(function chapterNavigation() { + document.addEventListener('keydown', function (e) { + if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; } + if (window.search && window.search.hasFocus()) { return; } + var html = document.querySelector('html'); + + function next() { + var nextButton = document.querySelector('.nav-chapters.next'); + if (nextButton) { + window.location.href = nextButton.href; + } + } + function prev() { + var previousButton = document.querySelector('.nav-chapters.previous'); + if (previousButton) { + window.location.href = previousButton.href; + } + } + switch (e.key) { + case 'ArrowRight': + e.preventDefault(); + if (html.dir == 'rtl') { + prev(); + } else { + next(); + } + break; + case 'ArrowLeft': + e.preventDefault(); + if (html.dir == 'rtl') { + next(); + } else { + prev(); + } + break; + } + }); +})(); + +(function clipboard() { + var clipButtons = document.querySelectorAll('.clip-button'); + + function hideTooltip(elem) { + elem.firstChild.innerText = ""; + elem.className = 'clip-button'; + } + + function showTooltip(elem, msg) { + elem.firstChild.innerText = msg; + elem.className = 'clip-button tooltipped'; + } + + var clipboardSnippets = new ClipboardJS('.clip-button', { + text: function (trigger) { + hideTooltip(trigger); + let playground = trigger.closest("pre"); + return playground_text(playground, false); + } + }); + + Array.from(clipButtons).forEach(function (clipButton) { + clipButton.addEventListener('mouseout', function (e) { + hideTooltip(e.currentTarget); + }); + }); + + clipboardSnippets.on('success', function (e) { + e.clearSelection(); + showTooltip(e.trigger, "Copied!"); + }); + + clipboardSnippets.on('error', function (e) { + showTooltip(e.trigger, "Clipboard error!"); + }); +})(); + +(function scrollToTop () { + var menuTitle = document.querySelector('.menu-title'); + + menuTitle.addEventListener('click', function () { + document.scrollingElement.scrollTo({ top: 0, behavior: 'smooth' }); + }); +})(); + +(function controllMenu() { + var menu = document.getElementById('menu-bar'); + + (function controllPosition() { + var scrollTop = document.scrollingElement.scrollTop; + var prevScrollTop = scrollTop; + var minMenuY = -menu.clientHeight - 50; + // When the script loads, the page can be at any scroll (e.g. if you reforesh it). + menu.style.top = scrollTop + 'px'; + // Same as parseInt(menu.style.top.slice(0, -2), but faster + var topCache = menu.style.top.slice(0, -2); + menu.classList.remove('sticky'); + var stickyCache = false; // Same as menu.classList.contains('sticky'), but faster + document.addEventListener('scroll', function () { + scrollTop = Math.max(document.scrollingElement.scrollTop, 0); + // `null` means that it doesn't need to be updated + var nextSticky = null; + var nextTop = null; + var scrollDown = scrollTop > prevScrollTop; + var menuPosAbsoluteY = topCache - scrollTop; + if (scrollDown) { + nextSticky = false; + if (menuPosAbsoluteY > 0) { + nextTop = prevScrollTop; + } + } else { + if (menuPosAbsoluteY > 0) { + nextSticky = true; + } else if (menuPosAbsoluteY < minMenuY) { + nextTop = prevScrollTop + minMenuY; + } + } + if (nextSticky === true && stickyCache === false) { + menu.classList.add('sticky'); + stickyCache = true; + } else if (nextSticky === false && stickyCache === true) { + menu.classList.remove('sticky'); + stickyCache = false; + } + if (nextTop !== null) { + menu.style.top = nextTop + 'px'; + topCache = nextTop; + } + prevScrollTop = scrollTop; + }, { passive: true }); + })(); + (function controllBorder() { + function updateBorder() { + if (menu.offsetTop === 0) { + menu.classList.remove('bordered'); + } else { + menu.classList.add('bordered'); + } + } + updateBorder(); + document.addEventListener('scroll', updateBorder, { passive: true }); + })(); +})(); diff --git a/builtin-filters.html b/builtin-filters.html new file mode 100644 index 0000000..7632ce7 --- /dev/null +++ b/builtin-filters.html @@ -0,0 +1,278 @@ + + + + + + Built-in Filters - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

Built-in Filters

+

While most applications will use user-defined filters, vidformer ships with a handful of built-in filters to get you started:

+

DrawText

+

DrawText does exactly what it sounds like: draw text on a frame.

+

For example:

+
DrawText(frame, text="Hello, world!", x=100, y=100, size=48, color="white")
+
+

BoundingBox

+

BoundingBox draws bounding boxes on a frame.

+

For example:

+
BoundingBox(frame, bounds=obj)
+
+

Where obj is JSON with this schema:

+
[
+  {
+    "class": "person",
+    "confidence": 0.916827917098999,
+    "x1": 683.0721842447916,
+    "y1": 100.92174338626751,
+    "x2": 1006.863525390625,
+    "y2": 720
+  },
+  {
+    "class": "dog",
+    "confidence": 0.902531921863556,
+    "x1": 360.8750813802083,
+    "y1": 47.983140622720974,
+    "x2": 606.76171875,
+    "y2": 717.9591837897462
+  }
+]
+
+

Scale

+

The Scale filter transforms one frame type to another. +It changes both resolution and pixel format. +This is the most important filter and is essential for building with vidformer.

+

Arguments:

+
Scale(
+    frame: Frame,
+    width: int = None,
+    height: int = None,
+    pix_fmt: str = None)
+
+

By default missing width, height and format values are set to match frame. +pix_fmt must match ffmpeg's name for a pixel format.

+

For example:

+
frame = Scale(frame, width=1280, height=720, pix_fmt="rgb24")
+
+

IPC

+

IPC allows for calling User-Defined Filters (UDFs) running on the same system. +It is an infrastructure-level filter and is used to implement other filters. +It is configured with a socket and func, the filter's name, both strings.

+

The IPC filter can not be directly invoked, rather IPC filters are constructed by a server upon request. +This can be difficult, but vidformer-py handles this for you. +As of right now IPC only supports rgb24 frames.

+

HStack & VStack

+

HStack & VStack allow for composing multiple frames together, stacking them either horizontally or vertically. +It tries to automatically find a reasonable layout.

+

Arguments:

+
HStack(
+    *frames: list[Frame],
+    width: int,
+    height: int,
+    format: str)
+
+

At least one frame is required, along with a width, height and format.

+

For example:

+
compilation = HStack(left_frame, right_frame, width=1280, height=720, format="rgb24")
+
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/clipboard.min.js b/clipboard.min.js new file mode 100644 index 0000000..02c549e --- /dev/null +++ b/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.4 + * https://zenorocha.github.io/clipboard.js + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return function(n){var o={};function r(t){if(o[t])return o[t].exports;var e=o[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=n,r.c=o,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n + + + + + Concepts & Data Model - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

Concepts & Data Model

+

vidformer builds on the data model introduced in the V2V paper.

+
    +
  • +

    Frames are a single image. +Frames are represented as their resolution and pixel format (the type and layout of pixels in memory, such as rgb24, gray8, or yuv420p).

    +
  • +
  • +

    Videos are sequences of frames represented as an array. +We index these arrays by rational numbers corresponding to their timestamp.

    +
  • +
  • +

    Filters are functions which construct a frame. +Filters can take inputs, such as frames or data. +For example, DrawText may draw some text on a frame.

    +
  • +
  • +

    Specs declarativly represent a video synthesis task. +They represent the construction of a result videos, which is itself modeled as an array.

    +
      +
    • Specs primairly contan domain and render functions. +
        +
      • A spec's domain function returns the timestamps of the output frames.
      • +
      • A spec's render function returns a composition of filters used to construct a frame at a spesific timestamp.
      • +
      +
    • +
    +
  • +
  • +

    Data Arrays allow using data in specs symbolically, as opposed to inserting constants directly into the spec. +These allow for deduplication and loading large data blobs efficiently.

    +
      +
    • Data Arrays can be backed by external data sources, such as SQL databases.
    • +
    +
  • +
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/crates.js b/crates.js new file mode 100644 index 0000000..1615775 --- /dev/null +++ b/crates.js @@ -0,0 +1,2 @@ +window.ALL_CRATES = ["vidformer"]; +//{"start":21,"fragment_lengths":[11]} \ No newline at end of file diff --git a/css/chrome.css b/css/chrome.css new file mode 100644 index 0000000..4cd7308 --- /dev/null +++ b/css/chrome.css @@ -0,0 +1,640 @@ +/* CSS for UI elements (a.k.a. chrome) */ + +html { + scrollbar-color: var(--scrollbar) var(--bg); +} +#searchresults a, +.content a:link, +a:visited, +a > .hljs { + color: var(--links); +} + +/* + body-container is necessary because mobile browsers don't seem to like + overflow-x on the body tag when there is a tag. +*/ +#body-container { + /* + This is used when the sidebar pushes the body content off the side of + the screen on small screens. Without it, dragging on mobile Safari + will want to reposition the viewport in a weird way. + */ + overflow-x: clip; +} + +/* Menu Bar */ + +#menu-bar, +#menu-bar-hover-placeholder { + z-index: 101; + margin: auto calc(0px - var(--page-padding)); +} +#menu-bar { + position: relative; + display: flex; + flex-wrap: wrap; + background-color: var(--bg); + border-block-end-color: var(--bg); + border-block-end-width: 1px; + border-block-end-style: solid; +} +#menu-bar.sticky, +#menu-bar-hover-placeholder:hover + #menu-bar, +#menu-bar:hover, +html.sidebar-visible #menu-bar { + position: -webkit-sticky; + position: sticky; + top: 0 !important; +} +#menu-bar-hover-placeholder { + position: sticky; + position: -webkit-sticky; + top: 0; + height: var(--menu-bar-height); +} +#menu-bar.bordered { + border-block-end-color: var(--table-border-color); +} +#menu-bar i, #menu-bar .icon-button { + position: relative; + padding: 0 8px; + z-index: 10; + line-height: var(--menu-bar-height); + cursor: pointer; + transition: color 0.5s; +} +@media only screen and (max-width: 420px) { + #menu-bar i, #menu-bar .icon-button { + padding: 0 5px; + } +} + +.icon-button { + border: none; + background: none; + padding: 0; + color: inherit; +} +.icon-button i { + margin: 0; +} + +.right-buttons { + margin: 0 15px; +} +.right-buttons a { + text-decoration: none; +} + +.left-buttons { + display: flex; + margin: 0 5px; +} +html:not(.js) .left-buttons button { + display: none; +} + +.menu-title { + display: inline-block; + font-weight: 200; + font-size: 2.4rem; + line-height: var(--menu-bar-height); + text-align: center; + margin: 0; + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.menu-title { + cursor: pointer; +} + +.menu-bar, +.menu-bar:visited, +.nav-chapters, +.nav-chapters:visited, +.mobile-nav-chapters, +.mobile-nav-chapters:visited, +.menu-bar .icon-button, +.menu-bar a i { + color: var(--icons); +} + +.menu-bar i:hover, +.menu-bar .icon-button:hover, +.nav-chapters:hover, +.mobile-nav-chapters i:hover { + color: var(--icons-hover); +} + +/* Nav Icons */ + +.nav-chapters { + font-size: 2.5em; + text-align: center; + text-decoration: none; + + position: fixed; + top: 0; + bottom: 0; + margin: 0; + max-width: 150px; + min-width: 90px; + + display: flex; + justify-content: center; + align-content: center; + flex-direction: column; + + transition: color 0.5s, background-color 0.5s; +} + +.nav-chapters:hover { + text-decoration: none; + background-color: var(--theme-hover); + transition: background-color 0.15s, color 0.15s; +} + +.nav-wrapper { + margin-block-start: 50px; + display: none; +} + +.mobile-nav-chapters { + font-size: 2.5em; + text-align: center; + text-decoration: none; + width: 90px; + border-radius: 5px; + background-color: var(--sidebar-bg); +} + +/* Only Firefox supports flow-relative values */ +.previous { float: left; } +[dir=rtl] .previous { float: right; } + +/* Only Firefox supports flow-relative values */ +.next { + float: right; + right: var(--page-padding); +} +[dir=rtl] .next { + float: left; + right: unset; + left: var(--page-padding); +} + +/* Use the correct buttons for RTL layouts*/ +[dir=rtl] .previous i.fa-angle-left:before {content:"\f105";} +[dir=rtl] .next i.fa-angle-right:before { content:"\f104"; } + +@media only screen and (max-width: 1080px) { + .nav-wide-wrapper { display: none; } + .nav-wrapper { display: block; } +} + +/* sidebar-visible */ +@media only screen and (max-width: 1380px) { + #sidebar-toggle-anchor:checked ~ .page-wrapper .nav-wide-wrapper { display: none; } + #sidebar-toggle-anchor:checked ~ .page-wrapper .nav-wrapper { display: block; } +} + +/* Inline code */ + +:not(pre) > .hljs { + display: inline; + padding: 0.1em 0.3em; + border-radius: 3px; +} + +:not(pre):not(a) > .hljs { + color: var(--inline-code-color); + overflow-x: initial; +} + +a:hover > .hljs { + text-decoration: underline; +} + +pre { + position: relative; +} +pre > .buttons { + position: absolute; + z-index: 100; + right: 0px; + top: 2px; + margin: 0px; + padding: 2px 0px; + + color: var(--sidebar-fg); + cursor: pointer; + visibility: hidden; + opacity: 0; + transition: visibility 0.1s linear, opacity 0.1s linear; +} +pre:hover > .buttons { + visibility: visible; + opacity: 1 +} +pre > .buttons :hover { + color: var(--sidebar-active); + border-color: var(--icons-hover); + background-color: var(--theme-hover); +} +pre > .buttons i { + margin-inline-start: 8px; +} +pre > .buttons button { + cursor: inherit; + margin: 0px 5px; + padding: 4px 4px 3px 5px; + font-size: 23px; + + border-style: solid; + border-width: 1px; + border-radius: 4px; + border-color: var(--icons); + background-color: var(--theme-popup-bg); + transition: 100ms; + transition-property: color,border-color,background-color; + color: var(--icons); +} + +pre > .buttons button.clip-button { + padding: 2px 4px 0px 6px; +} +pre > .buttons button.clip-button::before { + /* clipboard image from octicons (https://github.com/primer/octicons/tree/v2.0.0) MIT license + */ + content: url('data:image/svg+xml,\ +\ +\ +'); + filter: var(--copy-button-filter); +} +pre > .buttons button.clip-button:hover::before { + filter: var(--copy-button-filter-hover); +} + +@media (pointer: coarse) { + pre > .buttons button { + /* On mobile, make it easier to tap buttons. */ + padding: 0.3rem 1rem; + } + + .sidebar-resize-indicator { + /* Hide resize indicator on devices with limited accuracy */ + display: none; + } +} +pre > code { + display: block; + padding: 1rem; +} + +/* FIXME: ACE editors overlap their buttons because ACE does absolute + positioning within the code block which breaks padding. The only solution I + can think of is to move the padding to the outer pre tag (or insert a div + wrapper), but that would require fixing a whole bunch of CSS rules. +*/ +.hljs.ace_editor { + padding: 0rem 0rem; +} + +pre > .result { + margin-block-start: 10px; +} + +/* Search */ + +#searchresults a { + text-decoration: none; +} + +mark { + border-radius: 2px; + padding-block-start: 0; + padding-block-end: 1px; + padding-inline-start: 3px; + padding-inline-end: 3px; + margin-block-start: 0; + margin-block-end: -1px; + margin-inline-start: -3px; + margin-inline-end: -3px; + background-color: var(--search-mark-bg); + transition: background-color 300ms linear; + cursor: pointer; +} + +mark.fade-out { + background-color: rgba(0,0,0,0) !important; + cursor: auto; +} + +.searchbar-outer { + margin-inline-start: auto; + margin-inline-end: auto; + max-width: var(--content-max-width); +} + +#searchbar { + width: 100%; + margin-block-start: 5px; + margin-block-end: 0; + margin-inline-start: auto; + margin-inline-end: auto; + padding: 10px 16px; + transition: box-shadow 300ms ease-in-out; + border: 1px solid var(--searchbar-border-color); + border-radius: 3px; + background-color: var(--searchbar-bg); + color: var(--searchbar-fg); +} +#searchbar:focus, +#searchbar.active { + box-shadow: 0 0 3px var(--searchbar-shadow-color); +} + +.searchresults-header { + font-weight: bold; + font-size: 1em; + padding-block-start: 18px; + padding-block-end: 0; + padding-inline-start: 5px; + padding-inline-end: 0; + color: var(--searchresults-header-fg); +} + +.searchresults-outer { + margin-inline-start: auto; + margin-inline-end: auto; + max-width: var(--content-max-width); + border-block-end: 1px dashed var(--searchresults-border-color); +} + +ul#searchresults { + list-style: none; + padding-inline-start: 20px; +} +ul#searchresults li { + margin: 10px 0px; + padding: 2px; + border-radius: 2px; +} +ul#searchresults li.focus { + background-color: var(--searchresults-li-bg); +} +ul#searchresults span.teaser { + display: block; + clear: both; + margin-block-start: 5px; + margin-block-end: 0; + margin-inline-start: 20px; + margin-inline-end: 0; + font-size: 0.8em; +} +ul#searchresults span.teaser em { + font-weight: bold; + font-style: normal; +} + +/* Sidebar */ + +.sidebar { + position: fixed; + left: 0; + top: 0; + bottom: 0; + width: var(--sidebar-width); + font-size: 0.875em; + box-sizing: border-box; + -webkit-overflow-scrolling: touch; + overscroll-behavior-y: contain; + background-color: var(--sidebar-bg); + color: var(--sidebar-fg); +} +.sidebar-iframe-inner { + background-color: var(--sidebar-bg); + color: var(--sidebar-fg); + padding: 10px 10px; + margin: 0; + font-size: 1.4rem; +} +.sidebar-iframe-outer { + border: none; + height: 100%; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; +} +[dir=rtl] .sidebar { left: unset; right: 0; } +.sidebar-resizing { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; +} +html:not(.sidebar-resizing) .sidebar { + transition: transform 0.3s; /* Animation: slide away */ +} +.sidebar code { + line-height: 2em; +} +.sidebar .sidebar-scrollbox { + overflow-y: auto; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + padding: 10px 10px; +} +.sidebar .sidebar-resize-handle { + position: absolute; + cursor: col-resize; + width: 0; + right: calc(var(--sidebar-resize-indicator-width) * -1); + top: 0; + bottom: 0; + display: flex; + align-items: center; +} + +.sidebar-resize-handle .sidebar-resize-indicator { + width: 100%; + height: 12px; + background-color: var(--icons); + margin-inline-start: var(--sidebar-resize-indicator-space); +} + +[dir=rtl] .sidebar .sidebar-resize-handle { + left: calc(var(--sidebar-resize-indicator-width) * -1); + right: unset; +} +.js .sidebar .sidebar-resize-handle { + cursor: col-resize; + width: calc(var(--sidebar-resize-indicator-width) - var(--sidebar-resize-indicator-space)); +} +/* sidebar-hidden */ +#sidebar-toggle-anchor:not(:checked) ~ .sidebar { + transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width))); + z-index: -1; +} +[dir=rtl] #sidebar-toggle-anchor:not(:checked) ~ .sidebar { + transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width))); +} +.sidebar::-webkit-scrollbar { + background: var(--sidebar-bg); +} +.sidebar::-webkit-scrollbar-thumb { + background: var(--scrollbar); +} + +/* sidebar-visible */ +#sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width))); +} +[dir=rtl] #sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width))); +} +@media only screen and (min-width: 620px) { + #sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: none; + margin-inline-start: calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width)); + } + [dir=rtl] #sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: none; + } +} + +.chapter { + list-style: none outside none; + padding-inline-start: 0; + line-height: 2.2em; +} + +.chapter ol { + width: 100%; +} + +.chapter li { + display: flex; + color: var(--sidebar-non-existant); +} +.chapter li a { + display: block; + padding: 0; + text-decoration: none; + color: var(--sidebar-fg); +} + +.chapter li a:hover { + color: var(--sidebar-active); +} + +.chapter li a.active { + color: var(--sidebar-active); +} + +.chapter li > a.toggle { + cursor: pointer; + display: block; + margin-inline-start: auto; + padding: 0 10px; + user-select: none; + opacity: 0.68; +} + +.chapter li > a.toggle div { + transition: transform 0.5s; +} + +/* collapse the section */ +.chapter li:not(.expanded) + li > ol { + display: none; +} + +.chapter li.chapter-item { + line-height: 1.5em; + margin-block-start: 0.6em; +} + +.chapter li.expanded > a.toggle div { + transform: rotate(90deg); +} + +.spacer { + width: 100%; + height: 3px; + margin: 5px 0px; +} +.chapter .spacer { + background-color: var(--sidebar-spacer); +} + +@media (-moz-touch-enabled: 1), (pointer: coarse) { + .chapter li a { padding: 5px 0; } + .spacer { margin: 10px 0; } +} + +.section { + list-style: none outside none; + padding-inline-start: 20px; + line-height: 1.9em; +} + +/* Theme Menu Popup */ + +.theme-popup { + position: absolute; + left: 10px; + top: var(--menu-bar-height); + z-index: 1000; + border-radius: 4px; + font-size: 0.7em; + color: var(--fg); + background: var(--theme-popup-bg); + border: 1px solid var(--theme-popup-border); + margin: 0; + padding: 0; + list-style: none; + display: none; + /* Don't let the children's background extend past the rounded corners. */ + overflow: hidden; +} +[dir=rtl] .theme-popup { left: unset; right: 10px; } +.theme-popup .default { + color: var(--icons); +} +.theme-popup .theme { + width: 100%; + border: 0; + margin: 0; + padding: 2px 20px; + line-height: 25px; + white-space: nowrap; + text-align: start; + cursor: pointer; + color: inherit; + background: inherit; + font-size: inherit; +} +.theme-popup .theme:hover { + background-color: var(--theme-hover); +} + +.theme-selected::before { + display: inline-block; + content: "✓"; + margin-inline-start: -14px; + width: 14px; +} diff --git a/css/general.css b/css/general.css new file mode 100644 index 0000000..0862b51 --- /dev/null +++ b/css/general.css @@ -0,0 +1,242 @@ +/* Base styles and content styles */ + +:root { + /* Browser default font-size is 16px, this way 1 rem = 10px */ + font-size: 62.5%; + color-scheme: var(--color-scheme); +} + +html { + font-family: "Open Sans", sans-serif; + color: var(--fg); + background-color: var(--bg); + text-size-adjust: none; + -webkit-text-size-adjust: none; +} + +body { + margin: 0; + font-size: 1.6rem; + overflow-x: hidden; +} + +code { + font-family: var(--mono-font) !important; + font-size: var(--code-font-size); + direction: ltr !important; +} + +/* make long words/inline code not x overflow */ +main { + overflow-wrap: break-word; +} + +/* make wide tables scroll if they overflow */ +.table-wrapper { + overflow-x: auto; +} + +/* Don't change font size in headers. */ +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + font-size: unset; +} + +.left { float: left; } +.right { float: right; } +.boring { opacity: 0.6; } +.hide-boring .boring { display: none; } +.hidden { display: none !important; } + +h2, h3 { margin-block-start: 2.5em; } +h4, h5 { margin-block-start: 2em; } + +.header + .header h3, +.header + .header h4, +.header + .header h5 { + margin-block-start: 1em; +} + +h1:target::before, +h2:target::before, +h3:target::before, +h4:target::before, +h5:target::before, +h6:target::before { + display: inline-block; + content: "»"; + margin-inline-start: -30px; + width: 30px; +} + +/* This is broken on Safari as of version 14, but is fixed + in Safari Technology Preview 117 which I think will be Safari 14.2. + https://bugs.webkit.org/show_bug.cgi?id=218076 +*/ +:target { + /* Safari does not support logical properties */ + scroll-margin-top: calc(var(--menu-bar-height) + 0.5em); +} + +.page { + outline: 0; + padding: 0 var(--page-padding); + margin-block-start: calc(0px - var(--menu-bar-height)); /* Compensate for the #menu-bar-hover-placeholder */ +} +.page-wrapper { + box-sizing: border-box; + background-color: var(--bg); +} +.no-js .page-wrapper, +.js:not(.sidebar-resizing) .page-wrapper { + transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */ +} +[dir=rtl] .js:not(.sidebar-resizing) .page-wrapper { + transition: margin-right 0.3s ease, transform 0.3s ease; /* Animation: slide away */ +} + +.content { + overflow-y: auto; + padding: 0 5px 50px 5px; +} +.content main { + margin-inline-start: auto; + margin-inline-end: auto; + max-width: var(--content-max-width); +} +.content p { line-height: 1.45em; } +.content ol { line-height: 1.45em; } +.content ul { line-height: 1.45em; } +.content a { text-decoration: none; } +.content a:hover { text-decoration: underline; } +.content img, .content video { max-width: 100%; } +.content .header:link, +.content .header:visited { + color: var(--fg); +} +.content .header:link, +.content .header:visited:hover { + text-decoration: none; +} + +table { + margin: 0 auto; + border-collapse: collapse; +} +table td { + padding: 3px 20px; + border: 1px var(--table-border-color) solid; +} +table thead { + background: var(--table-header-bg); +} +table thead td { + font-weight: 700; + border: none; +} +table thead th { + padding: 3px 20px; +} +table thead tr { + border: 1px var(--table-header-bg) solid; +} +/* Alternate background colors for rows */ +table tbody tr:nth-child(2n) { + background: var(--table-alternate-bg); +} + + +blockquote { + margin: 20px 0; + padding: 0 20px; + color: var(--fg); + background-color: var(--quote-bg); + border-block-start: .1em solid var(--quote-border); + border-block-end: .1em solid var(--quote-border); +} + +.warning { + margin: 20px; + padding: 0 20px; + border-inline-start: 2px solid var(--warning-border); +} + +.warning:before { + position: absolute; + width: 3rem; + height: 3rem; + margin-inline-start: calc(-1.5rem - 21px); + content: "ⓘ"; + text-align: center; + background-color: var(--bg); + color: var(--warning-border); + font-weight: bold; + font-size: 2rem; +} + +blockquote .warning:before { + background-color: var(--quote-bg); +} + +kbd { + background-color: var(--table-border-color); + border-radius: 4px; + border: solid 1px var(--theme-popup-border); + box-shadow: inset 0 -1px 0 var(--theme-hover); + display: inline-block; + font-size: var(--code-font-size); + font-family: var(--mono-font); + line-height: 10px; + padding: 4px 5px; + vertical-align: middle; +} + +sup { + /* Set the line-height for superscript and footnote references so that there + isn't an awkward space appearing above lines that contain the footnote. + + See https://github.com/rust-lang/mdBook/pull/2443#discussion_r1813773583 + for an explanation. + */ + line-height: 0; +} + +:not(.footnote-definition) + .footnote-definition, +.footnote-definition + :not(.footnote-definition) { + margin-block-start: 2em; +} +.footnote-definition { + font-size: 0.9em; + margin: 0.5em 0; +} +.footnote-definition p { + display: inline; +} + +.tooltiptext { + position: absolute; + visibility: hidden; + color: #fff; + background-color: #333; + transform: translateX(-50%); /* Center by moving tooltip 50% of its width left */ + left: -8px; /* Half of the width of the icon */ + top: -35px; + font-size: 0.8em; + text-align: center; + border-radius: 6px; + padding: 5px 8px; + margin: 5px; + z-index: 1000; +} +.tooltipped .tooltiptext { + visibility: visible; +} + +.chapter li.part-title { + color: var(--sidebar-fg); + margin: 5px 0px; + font-weight: bold; +} + +.result-no-output { + font-style: italic; +} diff --git a/css/print.css b/css/print.css new file mode 100644 index 0000000..80ec3a5 --- /dev/null +++ b/css/print.css @@ -0,0 +1,50 @@ + +#sidebar, +#menu-bar, +.nav-chapters, +.mobile-nav-chapters { + display: none; +} + +#page-wrapper.page-wrapper { + transform: none !important; + margin-inline-start: 0px; + overflow-y: initial; +} + +#content { + max-width: none; + margin: 0; + padding: 0; +} + +.page { + overflow-y: initial; +} + +code { + direction: ltr !important; +} + +pre > .buttons { + z-index: 2; +} + +a, a:visited, a:active, a:hover { + color: #4183c4; + text-decoration: none; +} + +h1, h2, h3, h4, h5, h6 { + page-break-inside: avoid; + page-break-after: avoid; +} + +pre, code { + page-break-inside: avoid; + white-space: pre-wrap; +} + +.fa { + display: none !important; +} diff --git a/css/variables.css b/css/variables.css new file mode 100644 index 0000000..12d1db7 --- /dev/null +++ b/css/variables.css @@ -0,0 +1,309 @@ + +/* Globals */ + +:root { + --sidebar-width: 300px; + --sidebar-resize-indicator-width: 8px; + --sidebar-resize-indicator-space: 2px; + --page-padding: 15px; + --content-max-width: 750px; + --menu-bar-height: 50px; + --mono-font: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace; + --code-font-size: 0.875em /* please adjust the ace font size accordingly in editor.js */ +} + +/* Themes */ + +.ayu { + --bg: hsl(210, 25%, 8%); + --fg: #c5c5c5; + + --sidebar-bg: #14191f; + --sidebar-fg: #c8c9db; + --sidebar-non-existant: #5c6773; + --sidebar-active: #ffb454; + --sidebar-spacer: #2d334f; + + --scrollbar: var(--sidebar-fg); + + --icons: #737480; + --icons-hover: #b7b9cc; + + --links: #0096cf; + + --inline-code-color: #ffb454; + + --theme-popup-bg: #14191f; + --theme-popup-border: #5c6773; + --theme-hover: #191f26; + + --quote-bg: hsl(226, 15%, 17%); + --quote-border: hsl(226, 15%, 22%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(210, 25%, 13%); + --table-header-bg: hsl(210, 25%, 28%); + --table-alternate-bg: hsl(210, 25%, 11%); + + --searchbar-border-color: #848484; + --searchbar-bg: #424242; + --searchbar-fg: #fff; + --searchbar-shadow-color: #d4c89f; + --searchresults-header-fg: #666; + --searchresults-border-color: #888; + --searchresults-li-bg: #252932; + --search-mark-bg: #e3b171; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(45%) sepia(6%) saturate(621%) hue-rotate(198deg) brightness(99%) contrast(85%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(68%) sepia(55%) saturate(531%) hue-rotate(341deg) brightness(104%) contrast(101%); +} + +.coal { + --bg: hsl(200, 7%, 8%); + --fg: #98a3ad; + + --sidebar-bg: #292c2f; + --sidebar-fg: #a1adb8; + --sidebar-non-existant: #505254; + --sidebar-active: #3473ad; + --sidebar-spacer: #393939; + + --scrollbar: var(--sidebar-fg); + + --icons: #43484d; + --icons-hover: #b3c0cc; + + --links: #2b79a2; + + --inline-code-color: #c5c8c6; + + --theme-popup-bg: #141617; + --theme-popup-border: #43484d; + --theme-hover: #1f2124; + + --quote-bg: hsl(234, 21%, 18%); + --quote-border: hsl(234, 21%, 23%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(200, 7%, 13%); + --table-header-bg: hsl(200, 7%, 28%); + --table-alternate-bg: hsl(200, 7%, 11%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #b7b7b7; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #98a3ad; + --searchresults-li-bg: #2b2b2f; + --search-mark-bg: #355c7d; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(26%) sepia(8%) saturate(575%) hue-rotate(169deg) brightness(87%) contrast(82%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(36%) sepia(70%) saturate(503%) hue-rotate(167deg) brightness(98%) contrast(89%); +} + +.light, html:not(.js) { + --bg: hsl(0, 0%, 100%); + --fg: hsl(0, 0%, 0%); + + --sidebar-bg: #fafafa; + --sidebar-fg: hsl(0, 0%, 0%); + --sidebar-non-existant: #aaaaaa; + --sidebar-active: #1f1fff; + --sidebar-spacer: #f4f4f4; + + --scrollbar: #8F8F8F; + + --icons: #747474; + --icons-hover: #000000; + + --links: #20609f; + + --inline-code-color: #301900; + + --theme-popup-bg: #fafafa; + --theme-popup-border: #cccccc; + --theme-hover: #e6e6e6; + + --quote-bg: hsl(197, 37%, 96%); + --quote-border: hsl(197, 37%, 91%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(0, 0%, 95%); + --table-header-bg: hsl(0, 0%, 80%); + --table-alternate-bg: hsl(0, 0%, 97%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #fafafa; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #888; + --searchresults-li-bg: #e4f2fe; + --search-mark-bg: #a2cff5; + + --color-scheme: light; + + /* Same as `--icons` */ + --copy-button-filter: invert(45.49%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(14%) sepia(93%) saturate(4250%) hue-rotate(243deg) brightness(99%) contrast(130%); +} + +.navy { + --bg: hsl(226, 23%, 11%); + --fg: #bcbdd0; + + --sidebar-bg: #282d3f; + --sidebar-fg: #c8c9db; + --sidebar-non-existant: #505274; + --sidebar-active: #2b79a2; + --sidebar-spacer: #2d334f; + + --scrollbar: var(--sidebar-fg); + + --icons: #737480; + --icons-hover: #b7b9cc; + + --links: #2b79a2; + + --inline-code-color: #c5c8c6; + + --theme-popup-bg: #161923; + --theme-popup-border: #737480; + --theme-hover: #282e40; + + --quote-bg: hsl(226, 15%, 17%); + --quote-border: hsl(226, 15%, 22%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(226, 23%, 16%); + --table-header-bg: hsl(226, 23%, 31%); + --table-alternate-bg: hsl(226, 23%, 14%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #aeaec6; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #5f5f71; + --searchresults-border-color: #5c5c68; + --searchresults-li-bg: #242430; + --search-mark-bg: #a2cff5; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(51%) sepia(10%) saturate(393%) hue-rotate(198deg) brightness(86%) contrast(87%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(46%) sepia(20%) saturate(1537%) hue-rotate(156deg) brightness(85%) contrast(90%); +} + +.rust { + --bg: hsl(60, 9%, 87%); + --fg: #262625; + + --sidebar-bg: #3b2e2a; + --sidebar-fg: #c8c9db; + --sidebar-non-existant: #505254; + --sidebar-active: #e69f67; + --sidebar-spacer: #45373a; + + --scrollbar: var(--sidebar-fg); + + --icons: #737480; + --icons-hover: #262625; + + --links: #2b79a2; + + --inline-code-color: #6e6b5e; + + --theme-popup-bg: #e1e1db; + --theme-popup-border: #b38f6b; + --theme-hover: #99908a; + + --quote-bg: hsl(60, 5%, 75%); + --quote-border: hsl(60, 5%, 70%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(60, 9%, 82%); + --table-header-bg: #b3a497; + --table-alternate-bg: hsl(60, 9%, 84%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #fafafa; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #888; + --searchresults-li-bg: #dec2a2; + --search-mark-bg: #e69f67; + + /* Same as `--icons` */ + --copy-button-filter: invert(51%) sepia(10%) saturate(393%) hue-rotate(198deg) brightness(86%) contrast(87%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(77%) sepia(16%) saturate(1798%) hue-rotate(328deg) brightness(98%) contrast(83%); +} + +@media (prefers-color-scheme: dark) { + html:not(.js) { + --bg: hsl(200, 7%, 8%); + --fg: #98a3ad; + + --sidebar-bg: #292c2f; + --sidebar-fg: #a1adb8; + --sidebar-non-existant: #505254; + --sidebar-active: #3473ad; + --sidebar-spacer: #393939; + + --scrollbar: var(--sidebar-fg); + + --icons: #43484d; + --icons-hover: #b3c0cc; + + --links: #2b79a2; + + --inline-code-color: #c5c8c6; + + --theme-popup-bg: #141617; + --theme-popup-border: #43484d; + --theme-hover: #1f2124; + + --quote-bg: hsl(234, 21%, 18%); + --quote-border: hsl(234, 21%, 23%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(200, 7%, 13%); + --table-header-bg: hsl(200, 7%, 28%); + --table-alternate-bg: hsl(200, 7%, 11%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #b7b7b7; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #98a3ad; + --searchresults-li-bg: #2b2b2f; + --search-mark-bg: #355c7d; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(26%) sepia(8%) saturate(575%) hue-rotate(169deg) brightness(87%) contrast(82%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(36%) sepia(70%) saturate(503%) hue-rotate(167deg) brightness(98%) contrast(89%); + } +} diff --git a/elasticlunr.min.js b/elasticlunr.min.js new file mode 100644 index 0000000..94b20dd --- /dev/null +++ b/elasticlunr.min.js @@ -0,0 +1,10 @@ +/** + * elasticlunr - http://weixsong.github.io + * Lightweight full-text search engine in Javascript for browser search and offline search. - 0.9.5 + * + * Copyright (C) 2017 Oliver Nightingale + * Copyright (C) 2017 Wei Song + * MIT Licensed + * @license + */ +!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o + + + + + FAQ - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

FAQ

+

What video formats does vidformer support?

+

In short, essentially everything. +vidformer uses the FFmpeg/libav* libraries internally, so any media FFmpeg works with should work in vidformer as well. +We support many container formats (e.g., mp4, mov) and codecs (e.g., H.264, VP8).

+

A full list of supported codecs enabled in a vidformer build can be found by running:

+
vidformer-cli codecs
+
+

Can I access remote videos on the internet?

+

Yes, vidformer uses Apache OpenDAL for I/O, so most common data/storage access protocols are supported. +However, not all storage services are enabled in distributed binaries. +We guarantee that HTTP, S3, and the local filesystem always work.

+

How does vidformer compare to FFmpeg?

+

vidformer is far more expressive than the FFmpeg filter interface. +Mainly, vidformer is designed for work around data, so edits are created programatically and edits can reference data. +Also, vidformer enables serving resut videos on demand.

+

vidformer uses the FFmpeg/libav* libraries internally, so any media FFmpeg works with should also work in vidformer.

+

How does vidformer compare to OpenCV/cv2?

+

vidformer orchestrates data movment in video synthesis tasks, but does not implement image processing directly. +Most use cases will still use OpenCV for this.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/favicon.png b/favicon.png new file mode 100644 index 0000000..a5b1aa1 Binary files /dev/null and b/favicon.png differ diff --git a/favicon.svg b/favicon.svg new file mode 100644 index 0000000..90e0ea5 --- /dev/null +++ b/favicon.svg @@ -0,0 +1,22 @@ + + + + + diff --git a/filters.html b/filters.html new file mode 100644 index 0000000..a15b41b --- /dev/null +++ b/filters.html @@ -0,0 +1,215 @@ + + + + + + Filters - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/fonts/OPEN-SANS-LICENSE.txt b/fonts/OPEN-SANS-LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/fonts/OPEN-SANS-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/fonts/SOURCE-CODE-PRO-LICENSE.txt b/fonts/SOURCE-CODE-PRO-LICENSE.txt new file mode 100644 index 0000000..366206f --- /dev/null +++ b/fonts/SOURCE-CODE-PRO-LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/fonts/fonts.css b/fonts/fonts.css new file mode 100644 index 0000000..858efa5 --- /dev/null +++ b/fonts/fonts.css @@ -0,0 +1,100 @@ +/* Open Sans is licensed under the Apache License, Version 2.0. See http://www.apache.org/licenses/LICENSE-2.0 */ +/* Source Code Pro is under the Open Font License. See https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL */ + +/* open-sans-300 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 300; + src: local('Open Sans Light'), local('OpenSans-Light'), + url('open-sans-v17-all-charsets-300.woff2') format('woff2'); +} + +/* open-sans-300italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 300; + src: local('Open Sans Light Italic'), local('OpenSans-LightItalic'), + url('open-sans-v17-all-charsets-300italic.woff2') format('woff2'); +} + +/* open-sans-regular - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans Regular'), local('OpenSans-Regular'), + url('open-sans-v17-all-charsets-regular.woff2') format('woff2'); +} + +/* open-sans-italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 400; + src: local('Open Sans Italic'), local('OpenSans-Italic'), + url('open-sans-v17-all-charsets-italic.woff2') format('woff2'); +} + +/* open-sans-600 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 600; + src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), + url('open-sans-v17-all-charsets-600.woff2') format('woff2'); +} + +/* open-sans-600italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 600; + src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), + url('open-sans-v17-all-charsets-600italic.woff2') format('woff2'); +} + +/* open-sans-700 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 700; + src: local('Open Sans Bold'), local('OpenSans-Bold'), + url('open-sans-v17-all-charsets-700.woff2') format('woff2'); +} + +/* open-sans-700italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 700; + src: local('Open Sans Bold Italic'), local('OpenSans-BoldItalic'), + url('open-sans-v17-all-charsets-700italic.woff2') format('woff2'); +} + +/* open-sans-800 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 800; + src: local('Open Sans ExtraBold'), local('OpenSans-ExtraBold'), + url('open-sans-v17-all-charsets-800.woff2') format('woff2'); +} + +/* open-sans-800italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: italic; + font-weight: 800; + src: local('Open Sans ExtraBold Italic'), local('OpenSans-ExtraBoldItalic'), + url('open-sans-v17-all-charsets-800italic.woff2') format('woff2'); +} + +/* source-code-pro-500 - latin_vietnamese_latin-ext_greek_cyrillic-ext_cyrillic */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 500; + src: url('source-code-pro-v11-all-charsets-500.woff2') format('woff2'); +} diff --git a/fonts/open-sans-v17-all-charsets-300.woff2 b/fonts/open-sans-v17-all-charsets-300.woff2 new file mode 100644 index 0000000..9f51be3 Binary files /dev/null and b/fonts/open-sans-v17-all-charsets-300.woff2 differ diff --git a/fonts/open-sans-v17-all-charsets-300italic.woff2 b/fonts/open-sans-v17-all-charsets-300italic.woff2 new file mode 100644 index 0000000..2f54544 Binary files /dev/null and b/fonts/open-sans-v17-all-charsets-300italic.woff2 differ diff --git a/fonts/open-sans-v17-all-charsets-600.woff2 b/fonts/open-sans-v17-all-charsets-600.woff2 new file mode 100644 index 0000000..f503d55 Binary files /dev/null and b/fonts/open-sans-v17-all-charsets-600.woff2 differ diff --git a/fonts/open-sans-v17-all-charsets-600italic.woff2 b/fonts/open-sans-v17-all-charsets-600italic.woff2 new file mode 100644 index 0000000..c99aabe Binary files /dev/null and b/fonts/open-sans-v17-all-charsets-600italic.woff2 differ diff --git a/fonts/open-sans-v17-all-charsets-700.woff2 b/fonts/open-sans-v17-all-charsets-700.woff2 new file mode 100644 index 0000000..421a1ab Binary files /dev/null and b/fonts/open-sans-v17-all-charsets-700.woff2 differ diff --git a/fonts/open-sans-v17-all-charsets-700italic.woff2 b/fonts/open-sans-v17-all-charsets-700italic.woff2 new file mode 100644 index 0000000..12ce3d2 Binary files /dev/null and b/fonts/open-sans-v17-all-charsets-700italic.woff2 differ diff --git a/fonts/open-sans-v17-all-charsets-800.woff2 b/fonts/open-sans-v17-all-charsets-800.woff2 new file mode 100644 index 0000000..c94a223 Binary files /dev/null and b/fonts/open-sans-v17-all-charsets-800.woff2 differ diff --git a/fonts/open-sans-v17-all-charsets-800italic.woff2 b/fonts/open-sans-v17-all-charsets-800italic.woff2 new file mode 100644 index 0000000..eed7d3c Binary files /dev/null and b/fonts/open-sans-v17-all-charsets-800italic.woff2 differ diff --git a/fonts/open-sans-v17-all-charsets-italic.woff2 b/fonts/open-sans-v17-all-charsets-italic.woff2 new file mode 100644 index 0000000..398b68a Binary files /dev/null and b/fonts/open-sans-v17-all-charsets-italic.woff2 differ diff --git a/fonts/open-sans-v17-all-charsets-regular.woff2 b/fonts/open-sans-v17-all-charsets-regular.woff2 new file mode 100644 index 0000000..8383e94 Binary files /dev/null and b/fonts/open-sans-v17-all-charsets-regular.woff2 differ diff --git a/fonts/source-code-pro-v11-all-charsets-500.woff2 b/fonts/source-code-pro-v11-all-charsets-500.woff2 new file mode 100644 index 0000000..7222456 Binary files /dev/null and b/fonts/source-code-pro-v11-all-charsets-500.woff2 differ diff --git a/getting-started-cv2.html b/getting-started-cv2.html new file mode 100644 index 0000000..38e316b --- /dev/null +++ b/getting-started-cv2.html @@ -0,0 +1,278 @@ + + + + + + Getting Started - cv2 - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

Getting Started - cv2

+

This is a walkthrough of getting started with vidformer OpenCV cv2 compatability layer.

+
+

⚠️ Adding cv2 functions is a work in progress. See the cv2 filters page for which functions have been implemented.

+
+

Installation

+

See Installation guide

+

Or you can Open In Colab.

+
+

⚠️ Due to how Colab networking works, vidformer can't stream/play results in Colab, only save them to disk. cv2.vidplay() will not work!

+
+

Hello, world!

+

Copy in your video, or use ours:

+
curl -O https://f.dominik.win/data/dve2/tos_720p.mp4
+
+

Then just replace import cv2 with import vidformer.cv2 as cv2. +Here's our example script:

+
import vidformer.cv2 as cv2
+
+cap = cv2.VideoCapture("tos_720p.mp4")
+fps = cap.get(cv2.CAP_PROP_FPS)
+width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+out = cv2.VideoWriter("output.mp4", cv2.VideoWriter_fourcc(*"mp4v"),
+                        fps, (width, height))
+while True:
+    ret, frame = cap.read()
+    if not ret:
+      break
+
+    cv2.putText(frame, "Hello, World!", (100, 100), cv2.FONT_HERSHEY_SIMPLEX,
+                1, (255, 0, 0), 1)
+    out.write(frame)
+
+cap.release()
+out.release()
+
+

Stream the Results

+

Saving videos to disk works, but we can also display them in the notebook. +Since we stream the results and only render them on demand this can start practically instantly!

+

First, replace "output.mp4" with None to skip writing the video to disk. +Then you can use cv2.vidplay() to play the video!

+
import vidformer.cv2 as cv2
+
+cap = cv2.VideoCapture("tos_720p.mp4")
+fps = cap.get(cv2.CAP_PROP_FPS)
+width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+out = cv2.VideoWriter(None, cv2.VideoWriter_fourcc(*"mp4v"),
+                        fps, (width, height))
+while True:
+    ret, frame = cap.read()
+    if not ret:
+      break
+
+    cv2.putText(frame, "Hello, World!", (100, 100), cv2.FONT_HERSHEY_SIMPLEX,
+                1, (255, 0, 0), 1)
+    out.write(frame)
+
+cap.release()
+out.release()
+
+cv2.vidplay(out)
+
+
+

⚠️ By default cv2.vidplay() will return a video which plays in a Jupyter Notebook. If running outside a jupyter notebook you can pass method="link" to return a link instead.

+
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/getting-started-dsl.html b/getting-started-dsl.html new file mode 100644 index 0000000..a2611b5 --- /dev/null +++ b/getting-started-dsl.html @@ -0,0 +1,340 @@ + + + + + + Getting Started - DSL - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

Getting Started - DSL

+

This is a walkthrough of getting started with vidformer-py core DSL.

+

Installation

+

See Installation guide

+

Hello, world!

+
+

⚠️ We assume this is in a Jupyter notebook. If not then .play() won't work and you have to use .save() instead.

+
+

We start by connecting to a server and registering a source:

+
import vidformer as vf
+from fractions import Fraction
+
+server = vf.YrdenServer(domain='localhost', port=8000)
+
+tos = vf.Source(
+    server,
+    "tos_720p",     # name (for pretty printing)
+    "https://f.dominik.win/data/dve2/tos_720p.mp4",
+    stream=0,       # index of the video stream we want to use
+)
+
+print(tos.ts())
+print(tos.fmt())
+
+

This will print the timestamps of all the frames in the video, and then format information: +This may take a few seconds the first time, but frame times are cached afterwords.

+
> [Fraction(0, 1), Fraction(1, 24), Fraction(1, 12), Fraction(1, 8), ...]
+> {'width': 1280, 'height': 720, 'pix_fmt': 'yuv420p'}
+
+

Now lets create a 30 second clip starting at the 5 minute mark. +The source video is at at a constant 24 FPS, so lets create a 24 FPS output as well:

+
domain = [Fraction(i, 24) for i in range(24 * 30)]
+
+

Now we need to render each of these frames, so we define a render function.

+
def render(t: Fraction, i: int):
+    clip_start_point = Fraction(5 * 60, 1) # start at 5 * 60 seconds
+    return tos[t + clip_start_point]
+
+

We used timestamp-based indexing here, but you can also use integer indexing (tos.iloc[i + 5 * 60 * 24]).

+

Now we can create a spec and play it in the browser. +We create a spec from the resulting video's frame timestamps (domain), a function to construct each output frame (render), and the output videos format (matching tos.fmt()).

+
spec = vf.Spec(domain, render, tos.fmt())
+spec.play(server)
+
+

This plays this result: +

+
+

Some Jupyter environments are weird (i.e., VS Code), so .play() might not work. Using .play(..., method="iframe") may help.

+
+

It's worth noting that we are playing frames in order here and outputing video at the same framerate we recieved, but that doesn't need to be the case. +Here are some things other things you can now try:

+
    +
  • Reversing the video
  • +
  • Double the speed of the video +
      +
    • Either double the framerate or sample every other frame
    • +
    +
  • +
  • Shuffle the frames into a random order
  • +
  • Combining frames from multiple videos
  • +
  • Create a variable frame rate video +
      +
    • Note: .play() will not work with VFR, but .save() will.
    • +
    +
  • +
+

Bounding Boxes

+

Now let's overlay some bouding boxes over the entire clip:

+
# Load some data
+import urllib.request, json 
+with urllib.request.urlopen("https://f.dominik.win/data/dve2/tos_720p-objects.json") as r:
+    detections_per_frame = json.load(r)
+
+bbox = vf.Filter("BoundingBox") # load the built-in BoundingBox filter
+
+domain = tos.ts() # output should have same frame timestamps as our example clip
+
+def render(t, i):
+    return bbox(
+        tos[t],
+        bounds=detections_per_frame[i])
+
+spec = vf.Spec(domain, render, tos.fmt())
+spec.play(server)
+
+

This plays this result (video is just a sample clip): +

+

Composition

+

We can place frames next to each other with the HStack and VStack filters. +For example, HStack(left_frame, middle_frame, right_frame, width=1280, height=720, format="yuv420p") will place three frames side-by-side.

+

As a larger example, we can view a window function over frames as a 5x5 grid:

+
hstack = vf.Filter("HStack")
+vstack = vf.Filter("VStack")
+
+w, h = 1920, 1080
+
+def create_grid(tos, i, N, width, height, fmt="yuv420p"):
+    grid = []
+    for row in range(N):
+        columns = []
+        for col in range(N):
+            index = row * N + col
+            columns.append(tos.iloc[i + index])
+        grid.append(hstack(*columns, width=width, height=height//N, format=fmt))
+    final_grid = vstack(*grid, width=width, height=height, format=fmt)
+    return final_grid
+
+domain = [Fraction(i, 24) for i in range(0, 5000)]
+
+def render(t, i):
+    return create_grid(tos, i, 5, w, h)
+
+fmt = {'width': w, 'height': h, 'pix_fmt': 'yuv420p'}
+
+spec = vf.Spec(domain, render, fmt)
+spec.play(server)
+
+

This plays this result (video is just a sample clip): +

+

Viewing Telemetry (and User-Defined Filters)

+

This notebook shows how to build custom filters to overlay data.

+

This plays this result (video is just a sample clip): +

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/getting-started.html b/getting-started.html new file mode 100644 index 0000000..20de8d9 --- /dev/null +++ b/getting-started.html @@ -0,0 +1,215 @@ + + + + + + Getting Started - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/help.html b/help.html new file mode 100644 index 0000000..7a071e7 --- /dev/null +++ b/help.html @@ -0,0 +1 @@ +Help

Rustdoc help

Back
\ No newline at end of file diff --git a/highlight.css b/highlight.css new file mode 100644 index 0000000..352c79b --- /dev/null +++ b/highlight.css @@ -0,0 +1,83 @@ +/* + * An increased contrast highlighting scheme loosely based on the + * "Base16 Atelier Dune Light" theme by Bram de Haan + * (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) + * Original Base16 color scheme by Chris Kempson + * (https://github.com/chriskempson/base16) + */ + +/* Comment */ +.hljs-comment, +.hljs-quote { + color: #575757; +} + +/* Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-attr, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #d70025; +} + +/* Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #b21e00; +} + +/* Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #008200; +} + +/* Blue */ +.hljs-title, +.hljs-section { + color: #0030f2; +} + +/* Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #9d00ec; +} + +.hljs { + display: block; + overflow-x: auto; + background: #f6f7f6; + color: #000; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-addition { + color: #22863a; + background-color: #f0fff4; +} + +.hljs-deletion { + color: #b31d28; + background-color: #ffeef0; +} diff --git a/highlight.js b/highlight.js new file mode 100644 index 0000000..18d2434 --- /dev/null +++ b/highlight.js @@ -0,0 +1,54 @@ +/* + Highlight.js 10.1.1 (93fd0d73) + License: BSD-3-Clause + Copyright (c) 2006-2020, Ivan Sagalaev +*/ +var hljs=function(){"use strict";function e(n){Object.freeze(n);var t="function"==typeof n;return Object.getOwnPropertyNames(n).forEach((function(r){!Object.hasOwnProperty.call(n,r)||null===n[r]||"object"!=typeof n[r]&&"function"!=typeof n[r]||t&&("caller"===r||"callee"===r||"arguments"===r)||Object.isFrozen(n[r])||e(n[r])})),n}class n{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data}ignoreMatch(){this.ignore=!0}}function t(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function r(e,...n){var t={};for(const n in e)t[n]=e[n];return n.forEach((function(e){for(const n in e)t[n]=e[n]})),t}function a(e){return e.nodeName.toLowerCase()}var i=Object.freeze({__proto__:null,escapeHTML:t,inherit:r,nodeStream:function(e){var n=[];return function e(t,r){for(var i=t.firstChild;i;i=i.nextSibling)3===i.nodeType?r+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:r,node:i}),r=e(i,r),a(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:r,node:i}));return r}(e,0),n},mergeStreams:function(e,n,r){var i=0,s="",o=[];function l(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){s+=""}function d(e){("start"===e.event?c:u)(e.node)}for(;e.length||n.length;){var g=l();if(s+=t(r.substring(i,g[0].offset)),i=g[0].offset,g===e){o.reverse().forEach(u);do{d(g.splice(0,1)[0]),g=l()}while(g===e&&g.length&&g[0].offset===i);o.reverse().forEach(c)}else"start"===g[0].event?o.push(g[0].node):o.pop(),d(g.splice(0,1)[0])}return s+t(r.substr(i))}});const s="",o=e=>!!e.kind;class l{constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=t(e)}openNode(e){if(!o(e))return;let n=e.kind;e.sublanguage||(n=`${this.classPrefix}${n}`),this.span(n)}closeNode(e){o(e)&&(this.buffer+=s)}value(){return this.buffer}span(e){this.buffer+=``}}class c{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){const n={kind:e,children:[]};this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),n.children.forEach(n=>this._walk(e,n)),e.closeNode(n)),e}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every(e=>"string"==typeof e)?e.children=[e.children.join("")]:e.children.forEach(e=>{c._collapse(e)}))}}class u extends c{constructor(e){super(),this.options=e}addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const t=e.root;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){return new l(this,this.options).value()}finalize(){return!0}}function d(e){return e?"string"==typeof e?e:e.source:null}const g="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",h={begin:"\\\\[\\s\\S]",relevance:0},f={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[h]},p={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[h]},b={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},m=function(e,n,t={}){var a=r({className:"comment",begin:e,end:n,contains:[]},t);return a.contains.push(b),a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),a},v=m("//","$"),x=m("/\\*","\\*/"),E=m("#","$");var _=Object.freeze({__proto__:null,IDENT_RE:"[a-zA-Z]\\w*",UNDERSCORE_IDENT_RE:"[a-zA-Z_]\\w*",NUMBER_RE:"\\b\\d+(\\.\\d+)?",C_NUMBER_RE:g,BINARY_NUMBER_RE:"\\b(0b[01]+)",RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{const n=/^#![ ]*\//;return e.binary&&(e.begin=function(...e){return e.map(e=>d(e)).join("")}(n,/.*\b/,e.binary,/\b.*/)),r({className:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)},BACKSLASH_ESCAPE:h,APOS_STRING_MODE:f,QUOTE_STRING_MODE:p,PHRASAL_WORDS_MODE:b,COMMENT:m,C_LINE_COMMENT_MODE:v,C_BLOCK_COMMENT_MODE:x,HASH_COMMENT_MODE:E,NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?",relevance:0},C_NUMBER_MODE:{className:"number",begin:g,relevance:0},BINARY_NUMBER_MODE:{className:"number",begin:"\\b(0b[01]+)",relevance:0},CSS_NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[h,{begin:/\[/,end:/\]/,relevance:0,contains:[h]}]}]},TITLE_MODE:{className:"title",begin:"[a-zA-Z]\\w*",relevance:0},UNDERSCORE_TITLE_MODE:{className:"title",begin:"[a-zA-Z_]\\w*",relevance:0},METHOD_GUARD:{begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:function(e){return Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})}}),N="of and for in not or if then".split(" ");function w(e,n){return n?+n:function(e){return N.includes(e.toLowerCase())}(e)?0:1}const R=t,y=r,{nodeStream:k,mergeStreams:O}=i,M=Symbol("nomatch");return function(t){var a=[],i={},s={},o=[],l=!0,c=/(^(<[^>]+>|\t|)+|\n)/gm,g="Could not find the language '{}', did you forget to load/include a language module?";const h={disableAutodetect:!0,name:"Plain text",contains:[]};var f={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:null,__emitter:u};function p(e){return f.noHighlightRe.test(e)}function b(e,n,t,r){var a={code:n,language:e};S("before:highlight",a);var i=a.result?a.result:m(a.language,a.code,t,r);return i.code=a.code,S("after:highlight",i),i}function m(e,t,a,s){var o=t;function c(e,n){var t=E.case_insensitive?n[0].toLowerCase():n[0];return Object.prototype.hasOwnProperty.call(e.keywords,t)&&e.keywords[t]}function u(){null!=y.subLanguage?function(){if(""!==A){var e=null;if("string"==typeof y.subLanguage){if(!i[y.subLanguage])return void O.addText(A);e=m(y.subLanguage,A,!0,k[y.subLanguage]),k[y.subLanguage]=e.top}else e=v(A,y.subLanguage.length?y.subLanguage:null);y.relevance>0&&(I+=e.relevance),O.addSublanguage(e.emitter,e.language)}}():function(){if(!y.keywords)return void O.addText(A);let e=0;y.keywordPatternRe.lastIndex=0;let n=y.keywordPatternRe.exec(A),t="";for(;n;){t+=A.substring(e,n.index);const r=c(y,n);if(r){const[e,a]=r;O.addText(t),t="",I+=a,O.addKeyword(n[0],e)}else t+=n[0];e=y.keywordPatternRe.lastIndex,n=y.keywordPatternRe.exec(A)}t+=A.substr(e),O.addText(t)}(),A=""}function h(e){return e.className&&O.openNode(e.className),y=Object.create(e,{parent:{value:y}})}function p(e){return 0===y.matcher.regexIndex?(A+=e[0],1):(L=!0,0)}var b={};function x(t,r){var i=r&&r[0];if(A+=t,null==i)return u(),0;if("begin"===b.type&&"end"===r.type&&b.index===r.index&&""===i){if(A+=o.slice(r.index,r.index+1),!l){const n=Error("0 width match regex");throw n.languageName=e,n.badRule=b.rule,n}return 1}if(b=r,"begin"===r.type)return function(e){var t=e[0],r=e.rule;const a=new n(r),i=[r.__beforeBegin,r["on:begin"]];for(const n of i)if(n&&(n(e,a),a.ignore))return p(t);return r&&r.endSameAsBegin&&(r.endRe=RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),r.skip?A+=t:(r.excludeBegin&&(A+=t),u(),r.returnBegin||r.excludeBegin||(A=t)),h(r),r.returnBegin?0:t.length}(r);if("illegal"===r.type&&!a){const e=Error('Illegal lexeme "'+i+'" for mode "'+(y.className||"")+'"');throw e.mode=y,e}if("end"===r.type){var s=function(e){var t=e[0],r=o.substr(e.index),a=function e(t,r,a){let i=function(e,n){var t=e&&e.exec(n);return t&&0===t.index}(t.endRe,a);if(i){if(t["on:end"]){const e=new n(t);t["on:end"](r,e),e.ignore&&(i=!1)}if(i){for(;t.endsParent&&t.parent;)t=t.parent;return t}}if(t.endsWithParent)return e(t.parent,r,a)}(y,e,r);if(!a)return M;var i=y;i.skip?A+=t:(i.returnEnd||i.excludeEnd||(A+=t),u(),i.excludeEnd&&(A=t));do{y.className&&O.closeNode(),y.skip||y.subLanguage||(I+=y.relevance),y=y.parent}while(y!==a.parent);return a.starts&&(a.endSameAsBegin&&(a.starts.endRe=a.endRe),h(a.starts)),i.returnEnd?0:t.length}(r);if(s!==M)return s}if("illegal"===r.type&&""===i)return 1;if(B>1e5&&B>3*r.index)throw Error("potential infinite loop, way more iterations than matches");return A+=i,i.length}var E=T(e);if(!E)throw console.error(g.replace("{}",e)),Error('Unknown language: "'+e+'"');var _=function(e){function n(n,t){return RegExp(d(n),"m"+(e.case_insensitive?"i":"")+(t?"g":""))}class t{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=function(e){return RegExp(e.toString()+"|").exec("").length-1}(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const e=this.regexes.map(e=>e[1]);this.matcherRe=n(function(e,n="|"){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i0&&(a+=n),a+="(";o.length>0;){var l=t.exec(o);if(null==l){a+=o;break}a+=o.substring(0,l.index),o=o.substring(l.index+l[0].length),"\\"===l[0][0]&&l[1]?a+="\\"+(+l[1]+s):(a+=l[0],"("===l[0]&&r++)}a+=")"}return a}(e),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;const n=this.matcherRe.exec(e);if(!n)return null;const t=n.findIndex((e,n)=>n>0&&void 0!==e),r=this.matchIndexes[t];return n.splice(0,t),Object.assign(n,r)}}class a{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];const n=new t;return this.rules.slice(e).forEach(([e,t])=>n.addRule(e,t)),n.compile(),this.multiRegexes[e]=n,n}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;const t=n.exec(e);return t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count&&(this.regexIndex=0)),t}}function i(e,n){const t=e.input[e.index-1],r=e.input[e.index+e[0].length];"."!==t&&"."!==r||n.ignoreMatch()}if(e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return function t(s,o){const l=s;if(s.compiled)return l;s.compiled=!0,s.__beforeBegin=null,s.keywords=s.keywords||s.beginKeywords;let c=null;if("object"==typeof s.keywords&&(c=s.keywords.$pattern,delete s.keywords.$pattern),s.keywords&&(s.keywords=function(e,n){var t={};return"string"==typeof e?r("keyword",e):Object.keys(e).forEach((function(n){r(n,e[n])})),t;function r(e,r){n&&(r=r.toLowerCase()),r.split(" ").forEach((function(n){var r=n.split("|");t[r[0]]=[e,w(r[0],r[1])]}))}}(s.keywords,e.case_insensitive)),s.lexemes&&c)throw Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");return l.keywordPatternRe=n(s.lexemes||c||/\w+/,!0),o&&(s.beginKeywords&&(s.begin="\\b("+s.beginKeywords.split(" ").join("|")+")(?=\\b|\\s)",s.__beforeBegin=i),s.begin||(s.begin=/\B|\b/),l.beginRe=n(s.begin),s.endSameAsBegin&&(s.end=s.begin),s.end||s.endsWithParent||(s.end=/\B|\b/),s.end&&(l.endRe=n(s.end)),l.terminator_end=d(s.end)||"",s.endsWithParent&&o.terminator_end&&(l.terminator_end+=(s.end?"|":"")+o.terminator_end)),s.illegal&&(l.illegalRe=n(s.illegal)),void 0===s.relevance&&(s.relevance=1),s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((function(e){return function(e){return e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map((function(n){return r(e,{variants:null},n)}))),e.cached_variants?e.cached_variants:function e(n){return!!n&&(n.endsWithParent||e(n.starts))}(e)?r(e,{starts:e.starts?r(e.starts):null}):Object.isFrozen(e)?r(e):e}("self"===e?s:e)}))),s.contains.forEach((function(e){t(e,l)})),s.starts&&t(s.starts,o),l.matcher=function(e){const n=new a;return e.contains.forEach(e=>n.addRule(e.begin,{rule:e,type:"begin"})),e.terminator_end&&n.addRule(e.terminator_end,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n}(l),l}(e)}(E),N="",y=s||_,k={},O=new f.__emitter(f);!function(){for(var e=[],n=y;n!==E;n=n.parent)n.className&&e.unshift(n.className);e.forEach(e=>O.openNode(e))}();var A="",I=0,S=0,B=0,L=!1;try{for(y.matcher.considerAll();;){B++,L?L=!1:(y.matcher.lastIndex=S,y.matcher.considerAll());const e=y.matcher.exec(o);if(!e)break;const n=x(o.substring(S,e.index),e);S=e.index+n}return x(o.substr(S)),O.closeAllNodes(),O.finalize(),N=O.toHTML(),{relevance:I,value:N,language:e,illegal:!1,emitter:O,top:y}}catch(n){if(n.message&&n.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:n.message,context:o.slice(S-100,S+100),mode:n.mode},sofar:N,relevance:0,value:R(o),emitter:O};if(l)return{illegal:!1,relevance:0,value:R(o),emitter:O,language:e,top:y,errorRaised:n};throw n}}function v(e,n){n=n||f.languages||Object.keys(i);var t=function(e){const n={relevance:0,emitter:new f.__emitter(f),value:R(e),illegal:!1,top:h};return n.emitter.addText(e),n}(e),r=t;return n.filter(T).filter(I).forEach((function(n){var a=m(n,e,!1);a.language=n,a.relevance>r.relevance&&(r=a),a.relevance>t.relevance&&(r=t,t=a)})),r.language&&(t.second_best=r),t}function x(e){return f.tabReplace||f.useBR?e.replace(c,e=>"\n"===e?f.useBR?"
":e:f.tabReplace?e.replace(/\t/g,f.tabReplace):e):e}function E(e){let n=null;const t=function(e){var n=e.className+" ";n+=e.parentNode?e.parentNode.className:"";const t=f.languageDetectRe.exec(n);if(t){var r=T(t[1]);return r||(console.warn(g.replace("{}",t[1])),console.warn("Falling back to no-highlight mode for this block.",e)),r?t[1]:"no-highlight"}return n.split(/\s+/).find(e=>p(e)||T(e))}(e);if(p(t))return;S("before:highlightBlock",{block:e,language:t}),f.useBR?(n=document.createElement("div")).innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n"):n=e;const r=n.textContent,a=t?b(t,r,!0):v(r),i=k(n);if(i.length){const e=document.createElement("div");e.innerHTML=a.value,a.value=O(i,k(e),r)}a.value=x(a.value),S("after:highlightBlock",{block:e,result:a}),e.innerHTML=a.value,e.className=function(e,n,t){var r=n?s[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),e.includes(r)||a.push(r),a.join(" ").trim()}(e.className,t,a.language),e.result={language:a.language,re:a.relevance,relavance:a.relevance},a.second_best&&(e.second_best={language:a.second_best.language,re:a.second_best.relevance,relavance:a.second_best.relevance})}const N=()=>{if(!N.called){N.called=!0;var e=document.querySelectorAll("pre code");a.forEach.call(e,E)}};function T(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]}function A(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach(e=>{s[e]=n})}function I(e){var n=T(e);return n&&!n.disableAutodetect}function S(e,n){var t=e;o.forEach((function(e){e[t]&&e[t](n)}))}Object.assign(t,{highlight:b,highlightAuto:v,fixMarkup:x,highlightBlock:E,configure:function(e){f=y(f,e)},initHighlighting:N,initHighlightingOnLoad:function(){window.addEventListener("DOMContentLoaded",N,!1)},registerLanguage:function(e,n){var r=null;try{r=n(t)}catch(n){if(console.error("Language definition for '{}' could not be registered.".replace("{}",e)),!l)throw n;console.error(n),r=h}r.name||(r.name=e),i[e]=r,r.rawDefinition=n.bind(null,t),r.aliases&&A(r.aliases,{languageName:e})},listLanguages:function(){return Object.keys(i)},getLanguage:T,registerAliases:A,requireLanguage:function(e){var n=T(e);if(n)return n;throw Error("The '{}' language is required, but not loaded.".replace("{}",e))},autoDetection:I,inherit:y,addPlugin:function(e){o.push(e)}}),t.debugMode=function(){l=!1},t.safeMode=function(){l=!0},t.versionString="10.1.1";for(const n in _)"object"==typeof _[n]&&e(_[n]);return Object.assign(t,_),t}({})}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs); +hljs.registerLanguage("apache",function(){"use strict";return function(e){var n={className:"number",begin:"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?"};return{name:"Apache config",aliases:["apacheconf"],case_insensitive:!0,contains:[e.HASH_COMMENT_MODE,{className:"section",begin:"",contains:[n,{className:"number",begin:":\\d{1,5}"},e.inherit(e.QUOTE_STRING_MODE,{relevance:0})]},{className:"attribute",begin:/\w+/,relevance:0,keywords:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{end:/$/,relevance:0,keywords:{literal:"on off all deny allow"},contains:[{className:"meta",begin:"\\s\\[",end:"\\]$"},{className:"variable",begin:"[\\$%]\\{",end:"\\}",contains:["self",{className:"number",begin:"[\\$%]\\d+"}]},n,{className:"number",begin:"\\d+"},e.QUOTE_STRING_MODE]}}],illegal:/\S/}}}()); +hljs.registerLanguage("bash",function(){"use strict";return function(e){const s={};Object.assign(s,{className:"variable",variants:[{begin:/\$[\w\d#@][\w\d_]*/},{begin:/\$\{/,end:/\}/,contains:[{begin:/:-/,contains:[s]}]}]});const t={className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},n={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,t]};t.contains.push(n);const a={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,s]},i=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10}),c={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b-?[a-z\._]+\b/,keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},contains:[i,e.SHEBANG(),c,a,e.HASH_COMMENT_MODE,n,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},s]}}}()); +hljs.registerLanguage("c-like",function(){"use strict";return function(e){function t(e){return"(?:"+e+")?"}var n="(decltype\\(auto\\)|"+t("[a-zA-Z_]\\w*::")+"[a-zA-Z_]\\w*"+t("<.*?>")+")",r={className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},a={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",end:"'",illegal:"."},e.END_SAME_AS_BEGIN({begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},i={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},s={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{"meta-keyword":"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},e.inherit(a,{className:"meta-string"}),{className:"meta-string",begin:/<.*?>/,end:/$/,illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},o={className:"title",begin:t("[a-zA-Z_]\\w*::")+e.IDENT_RE,relevance:0},c=t("[a-zA-Z_]\\w*::")+e.IDENT_RE+"\\s*\\(",l={keyword:"int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid wchar_t short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignas alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict final override atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq",built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary",literal:"true false nullptr NULL"},d=[r,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,i,a],_={variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],keywords:l,contains:d.concat([{begin:/\(/,end:/\)/,keywords:l,contains:d.concat(["self"]),relevance:0}]),relevance:0},u={className:"function",begin:"("+n+"[\\*&\\s]+)+"+c,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:l,illegal:/[^\w\s\*&:<>]/,contains:[{begin:"decltype\\(auto\\)",keywords:l,relevance:0},{begin:c,returnBegin:!0,contains:[o],relevance:0},{className:"params",begin:/\(/,end:/\)/,keywords:l,relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,i,r,{begin:/\(/,end:/\)/,keywords:l,relevance:0,contains:["self",e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,i,r]}]},r,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s]};return{aliases:["c","cc","h","c++","h++","hpp","hh","hxx","cxx"],keywords:l,disableAutodetect:!0,illegal:"",keywords:l,contains:["self",r]},{begin:e.IDENT_RE+"::",keywords:l},{className:"class",beginKeywords:"class struct",end:/[{;:]/,contains:[{begin://,contains:["self"]},e.TITLE_MODE]}]),exports:{preprocessor:s,strings:a,keywords:l}}}}()); +hljs.registerLanguage("c",function(){"use strict";return function(e){var n=e.getLanguage("c-like").rawDefinition();return n.name="C",n.aliases=["c","h"],n}}()); +hljs.registerLanguage("coffeescript",function(){"use strict";const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);return function(r){var t={keyword:e.concat(["then","unless","until","loop","by","when","and","or","is","isnt","not"]).filter((e=>n=>!e.includes(n))(["var","const","let","function","static"])).join(" "),literal:n.concat(["yes","no","on","off"]).join(" "),built_in:a.concat(["npm","print"]).join(" ")},i="[A-Za-z$_][0-9A-Za-z$_]*",s={className:"subst",begin:/#\{/,end:/}/,keywords:t},o=[r.BINARY_NUMBER_MODE,r.inherit(r.C_NUMBER_MODE,{starts:{end:"(\\s*/)?",relevance:0}}),{className:"string",variants:[{begin:/'''/,end:/'''/,contains:[r.BACKSLASH_ESCAPE]},{begin:/'/,end:/'/,contains:[r.BACKSLASH_ESCAPE]},{begin:/"""/,end:/"""/,contains:[r.BACKSLASH_ESCAPE,s]},{begin:/"/,end:/"/,contains:[r.BACKSLASH_ESCAPE,s]}]},{className:"regexp",variants:[{begin:"///",end:"///",contains:[s,r.HASH_COMMENT_MODE]},{begin:"//[gim]{0,3}(?=\\W)",relevance:0},{begin:/\/(?![ *]).*?(?![\\]).\/[gim]{0,3}(?=\W)/}]},{begin:"@"+i},{subLanguage:"javascript",excludeBegin:!0,excludeEnd:!0,variants:[{begin:"```",end:"```"},{begin:"`",end:"`"}]}];s.contains=o;var c=r.inherit(r.TITLE_MODE,{begin:i}),l={className:"params",begin:"\\([^\\(]",returnBegin:!0,contains:[{begin:/\(/,end:/\)/,keywords:t,contains:["self"].concat(o)}]};return{name:"CoffeeScript",aliases:["coffee","cson","iced"],keywords:t,illegal:/\/\*/,contains:o.concat([r.COMMENT("###","###"),r.HASH_COMMENT_MODE,{className:"function",begin:"^\\s*"+i+"\\s*=\\s*(\\(.*\\))?\\s*\\B[-=]>",end:"[-=]>",returnBegin:!0,contains:[c,l]},{begin:/[:\(,=]\s*/,relevance:0,contains:[{className:"function",begin:"(\\(.*\\))?\\s*\\B[-=]>",end:"[-=]>",returnBegin:!0,contains:[l]}]},{className:"class",beginKeywords:"class",end:"$",illegal:/[:="\[\]]/,contains:[{beginKeywords:"extends",endsWithParent:!0,illegal:/[:="\[\]]/,contains:[c]},c]},{begin:i+":",end:":",returnBegin:!0,returnEnd:!0,relevance:0}])}}}()); +hljs.registerLanguage("cpp",function(){"use strict";return function(e){var t=e.getLanguage("c-like").rawDefinition();return t.disableAutodetect=!1,t.name="C++",t.aliases=["cc","c++","h++","hpp","hh","hxx","cxx"],t}}()); +hljs.registerLanguage("csharp",function(){"use strict";return function(e){var n={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let nameof on orderby partial remove select set value var when where yield",literal:"null false true"},i=e.inherit(e.TITLE_MODE,{begin:"[a-zA-Z](\\.?\\w)*"}),a={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},s={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]},t=e.inherit(s,{illegal:/\n/}),l={className:"subst",begin:"{",end:"}",keywords:n},r=e.inherit(l,{illegal:/\n/}),c={className:"string",begin:/\$"/,end:'"',illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},e.BACKSLASH_ESCAPE,r]},o={className:"string",begin:/\$@"/,end:'"',contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},l]},g=e.inherit(o,{illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},r]});l.contains=[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.C_BLOCK_COMMENT_MODE],r.contains=[g,c,t,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.inherit(e.C_BLOCK_COMMENT_MODE,{illegal:/\n/})];var d={variants:[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},E={begin:"<",end:">",contains:[{beginKeywords:"in out"},i]},_=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",b={begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"],keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0,contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{begin:"\x3c!--|--\x3e"},{begin:""}]}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",end:"$",keywords:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},d,a,{beginKeywords:"class interface",end:/[{;=]/,illegal:/[^\s:,]/,contains:[{beginKeywords:"where class"},i,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace",end:/[{;=]/,illegal:/[^\s:]/,contains:[i,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta",begin:"^\\s*\\[",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{className:"meta-string",begin:/"/,end:/"/}]},{beginKeywords:"new return throw await else",relevance:0},{className:"function",begin:"("+_+"\\s+)+"+e.IDENT_RE+"\\s*(\\<.+\\>)?\\s*\\(",returnBegin:!0,end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{begin:e.IDENT_RE+"\\s*(\\<.+\\>)?\\s*\\(",returnBegin:!0,contains:[e.TITLE_MODE,E],relevance:0},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0,contains:[d,a,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},b]}}}()); +hljs.registerLanguage("css",function(){"use strict";return function(e){var n={begin:/(?:[A-Z\_\.\-]+|--[a-zA-Z0-9_-]+)\s*:/,returnBegin:!0,end:";",endsWithParent:!0,contains:[{className:"attribute",begin:/\S/,end:":",excludeEnd:!0,starts:{endsWithParent:!0,excludeEnd:!0,contains:[{begin:/[\w-]+\(/,returnBegin:!0,contains:[{className:"built_in",begin:/[\w-]+/},{begin:/\(/,end:/\)/,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}]},e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{className:"number",begin:"#[0-9A-Fa-f]+"},{className:"meta",begin:"!important"}]}}]};return{name:"CSS",case_insensitive:!0,illegal:/[=\/|'\$]/,contains:[e.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/},{className:"selector-class",begin:/\.[A-Za-z0-9_-]+/},{className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"@(page|font-face)",lexemes:"@[a-z-]+",keywords:"@page @font-face"},{begin:"@",end:"[{;]",illegal:/:/,returnBegin:!0,contains:[{className:"keyword",begin:/@\-?\w[\w]*(\-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:"and or not only",contains:[{begin:/[a-z-]+:/,className:"attribute"},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},{begin:"{",end:"}",illegal:/\S/,contains:[e.C_BLOCK_COMMENT_MODE,n]}]}}}()); +hljs.registerLanguage("diff",function(){"use strict";return function(e){return{name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,variants:[{begin:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{begin:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{begin:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{className:"comment",variants:[{begin:/Index: /,end:/$/},{begin:/={3,}/,end:/$/},{begin:/^\-{3}/,end:/$/},{begin:/^\*{3} /,end:/$/},{begin:/^\+{3}/,end:/$/},{begin:/^\*{15}$/}]},{className:"addition",begin:"^\\+",end:"$"},{className:"deletion",begin:"^\\-",end:"$"},{className:"addition",begin:"^\\!",end:"$"}]}}}()); +hljs.registerLanguage("go",function(){"use strict";return function(e){var n={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",literal:"true false iota nil",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};return{name:"Go",aliases:["golang"],keywords:n,illegal:"e(n)).join("")}return function(a){var s={className:"number",relevance:0,variants:[{begin:/([\+\-]+)?[\d]+_[\d_]+/},{begin:a.NUMBER_RE}]},i=a.COMMENT();i.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];var t={className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)}/}]},r={className:"literal",begin:/\bon|off|true|false|yes|no\b/},l={className:"string",contains:[a.BACKSLASH_ESCAPE],variants:[{begin:"'''",end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"'},{begin:"'",end:"'"}]},c={begin:/\[/,end:/\]/,contains:[i,r,t,l,s,"self"],relevance:0},g="("+[/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/].map(n=>e(n)).join("|")+")";return{name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/,contains:[i,{className:"section",begin:/\[+/,end:/\]+/},{begin:n(g,"(\\s*\\.\\s*",g,")*",n("(?=",/\s*=\s*[^#\s]/,")")),className:"attr",starts:{end:/$/,contains:[i,c,r,t,l,s]}}]}}}()); +hljs.registerLanguage("java",function(){"use strict";function e(e){return e?"string"==typeof e?e:e.source:null}function n(e){return a("(",e,")?")}function a(...n){return n.map(n=>e(n)).join("")}function s(...n){return"("+n.map(n=>e(n)).join("|")+")"}return function(e){var t="false synchronized int abstract float private char boolean var static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",i={className:"meta",begin:"@[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*",contains:[{begin:/\(/,end:/\)/,contains:["self"]}]},r=e=>a("[",e,"]+([",e,"_]*[",e,"]+)?"),c={className:"number",variants:[{begin:`\\b(0[bB]${r("01")})[lL]?`},{begin:`\\b(0${r("0-7")})[dDfFlL]?`},{begin:a(/\b0[xX]/,s(a(r("a-fA-F0-9"),/\./,r("a-fA-F0-9")),a(r("a-fA-F0-9"),/\.?/),a(/\./,r("a-fA-F0-9"))),/([pP][+-]?(\d+))?/,/[fFdDlL]?/)},{begin:a(/\b/,s(a(/\d*\./,r("\\d")),r("\\d")),/[eE][+-]?[\d]+[dDfF]?/)},{begin:a(/\b/,r(/\d/),n(/\.?/),n(r(/\d/)),/[dDfFlL]?/)}],relevance:0};return{name:"Java",aliases:["jsp"],keywords:t,illegal:/<\/|#/,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"class",beginKeywords:"class interface",end:/[{;=]/,excludeEnd:!0,keywords:"class interface",illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"new throw return else",relevance:0},{className:"function",begin:"([À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(<[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(\\s*,\\s*[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*)*>)?\\s+)+"+e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:t,contains:[{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/,keywords:t,relevance:0,contains:[i,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},c,i]}}}()); +hljs.registerLanguage("javascript",function(){"use strict";const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);function s(e){return r("(?=",e,")")}function r(...e){return e.map(e=>(function(e){return e?"string"==typeof e?e:e.source:null})(e)).join("")}return function(t){var i="[A-Za-z$_][0-9A-Za-z$_]*",c={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/},o={$pattern:"[A-Za-z$_][0-9A-Za-z$_]*",keyword:e.join(" "),literal:n.join(" "),built_in:a.join(" ")},l={className:"number",variants:[{begin:"\\b(0[bB][01]+)n?"},{begin:"\\b(0[oO][0-7]+)n?"},{begin:t.C_NUMBER_RE+"n?"}],relevance:0},E={className:"subst",begin:"\\$\\{",end:"\\}",keywords:o,contains:[]},d={begin:"html`",end:"",starts:{end:"`",returnEnd:!1,contains:[t.BACKSLASH_ESCAPE,E],subLanguage:"xml"}},g={begin:"css`",end:"",starts:{end:"`",returnEnd:!1,contains:[t.BACKSLASH_ESCAPE,E],subLanguage:"css"}},u={className:"string",begin:"`",end:"`",contains:[t.BACKSLASH_ESCAPE,E]};E.contains=[t.APOS_STRING_MODE,t.QUOTE_STRING_MODE,d,g,u,l,t.REGEXP_MODE];var b=E.contains.concat([{begin:/\(/,end:/\)/,contains:["self"].concat(E.contains,[t.C_BLOCK_COMMENT_MODE,t.C_LINE_COMMENT_MODE])},t.C_BLOCK_COMMENT_MODE,t.C_LINE_COMMENT_MODE]),_={className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:b};return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:o,contains:[t.SHEBANG({binary:"node",relevance:5}),{className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},t.APOS_STRING_MODE,t.QUOTE_STRING_MODE,d,g,u,t.C_LINE_COMMENT_MODE,t.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+",contains:[{className:"type",begin:"\\{",end:"\\}",relevance:0},{className:"variable",begin:i+"(?=\\s*(-)|$)",endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,relevance:0}]}]}),t.C_BLOCK_COMMENT_MODE,l,{begin:r(/[{,\n]\s*/,s(r(/(((\/\/.*)|(\/\*(.|\n)*\*\/))\s*)*/,i+"\\s*:"))),relevance:0,contains:[{className:"attr",begin:i+s("\\s*:"),relevance:0}]},{begin:"("+t.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[t.C_LINE_COMMENT_MODE,t.C_BLOCK_COMMENT_MODE,t.REGEXP_MODE,{className:"function",begin:"(\\([^(]*(\\([^(]*(\\([^(]*\\))?\\))?\\)|"+t.UNDERSCORE_IDENT_RE+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:t.UNDERSCORE_IDENT_RE},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:o,contains:b}]}]},{begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{variants:[{begin:"<>",end:""},{begin:c.begin,end:c.end}],subLanguage:"xml",contains:[{begin:c.begin,end:c.end,skip:!0,contains:["self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/\{/,excludeEnd:!0,contains:[t.inherit(t.TITLE_MODE,{begin:i}),_],illegal:/\[|%/},{begin:/\$[(.]/},t.METHOD_GUARD,{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends"},t.UNDERSCORE_TITLE_MODE]},{beginKeywords:"constructor",end:/\{/,excludeEnd:!0},{begin:"(get|set)\\s+(?="+i+"\\()",end:/{/,keywords:"get set",contains:[t.inherit(t.TITLE_MODE,{begin:i}),{begin:/\(\)/},_]}],illegal:/#(?!!)/}}}()); +hljs.registerLanguage("json",function(){"use strict";return function(n){var e={literal:"true false null"},i=[n.C_LINE_COMMENT_MODE,n.C_BLOCK_COMMENT_MODE],t=[n.QUOTE_STRING_MODE,n.C_NUMBER_MODE],a={end:",",endsWithParent:!0,excludeEnd:!0,contains:t,keywords:e},l={begin:"{",end:"}",contains:[{className:"attr",begin:/"/,end:/"/,contains:[n.BACKSLASH_ESCAPE],illegal:"\\n"},n.inherit(a,{begin:/:/})].concat(i),illegal:"\\S"},s={begin:"\\[",end:"\\]",contains:[n.inherit(a)],illegal:"\\S"};return t.push(l,s),i.forEach((function(n){t.push(n)})),{name:"JSON",contains:t,keywords:e,illegal:"\\S"}}}()); +hljs.registerLanguage("kotlin",function(){"use strict";return function(e){var n={keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual trait volatile transient native default",built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing",literal:"true false null"},a={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@"},i={className:"subst",begin:"\\${",end:"}",contains:[e.C_NUMBER_MODE]},s={className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},t={className:"string",variants:[{begin:'"""',end:'"""(?=[^"])',contains:[s,i]},{begin:"'",end:"'",illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/,contains:[e.BACKSLASH_ESCAPE,s,i]}]};i.contains.push(t);var r={className:"meta",begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?"},l={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/,end:/\)/,contains:[e.inherit(t,{className:"meta-string"})]}]},c=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),o={variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/,contains:[]}]},d=o;return d.variants[1].contains=[o],o.variants[1].contains=[d],{name:"Kotlin",aliases:["kt"],keywords:n,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,c,{className:"keyword",begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol",begin:/@\w+/}]}},a,r,l,{className:"function",beginKeywords:"fun",end:"[(]|$",returnBegin:!0,excludeEnd:!0,keywords:n,illegal:/fun\s+(<.*>)?[^\s\(]+(\s+[^\s\(]+)\s*=/,relevance:5,contains:[{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://,keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/,endsWithParent:!0,contains:[o,e.C_LINE_COMMENT_MODE,c],relevance:0},e.C_LINE_COMMENT_MODE,c,r,l,t,e.C_NUMBER_MODE]},c]},{className:"class",beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0,illegal:"extends implements",contains:[{beginKeywords:"public protected internal private constructor"},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/,excludeBegin:!0,returnEnd:!0},r,l]},t,{className:"meta",begin:"^#!/usr/bin/env",end:"$",illegal:"\n"},{className:"number",begin:"\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",relevance:0}]}}}()); +hljs.registerLanguage("less",function(){"use strict";return function(e){var n="([\\w-]+|@{[\\w-]+})",a=[],s=[],t=function(e){return{className:"string",begin:"~?"+e+".*?"+e}},r=function(e,n,a){return{className:e,begin:n,relevance:a}},i={begin:"\\(",end:"\\)",contains:s,relevance:0};s.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,t("'"),t('"'),e.CSS_NUMBER_MODE,{begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]",excludeEnd:!0}},r("number","#[0-9A-Fa-f]+\\b"),i,r("variable","@@?[\\w-]+",10),r("variable","@{[\\w-]+}"),r("built_in","~?`[^`]*?`"),{className:"attribute",begin:"[\\w-]+\\s*:",end:":",returnBegin:!0,excludeEnd:!0},{className:"meta",begin:"!important"});var c=s.concat({begin:"{",end:"}",contains:a}),l={beginKeywords:"when",endsWithParent:!0,contains:[{beginKeywords:"and not"}].concat(s)},o={begin:n+"\\s*:",returnBegin:!0,end:"[;}]",relevance:0,contains:[{className:"attribute",begin:n,end:":",excludeEnd:!0,starts:{endsWithParent:!0,illegal:"[<=$]",relevance:0,contains:s}}]},g={className:"keyword",begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b",starts:{end:"[;{}]",returnEnd:!0,contains:s,relevance:0}},d={className:"variable",variants:[{begin:"@[\\w-]+\\s*:",relevance:15},{begin:"@[\\w-]+"}],starts:{end:"[;}]",returnEnd:!0,contains:c}},b={variants:[{begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:n,end:"{"}],returnBegin:!0,returnEnd:!0,illegal:"[<='$\"]",relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,l,r("keyword","all\\b"),r("variable","@{[\\w-]+}"),r("selector-tag",n+"%?",0),r("selector-id","#"+n),r("selector-class","\\."+n,0),r("selector-tag","&",0),{className:"selector-attr",begin:"\\[",end:"\\]"},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"\\(",end:"\\)",contains:c},{begin:"!important"}]};return a.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,g,d,o,b),{name:"Less",case_insensitive:!0,illegal:"[=>'/<($\"]",contains:a}}}()); +hljs.registerLanguage("lua",function(){"use strict";return function(e){var t={begin:"\\[=*\\[",end:"\\]=*\\]",contains:["self"]},a=[e.COMMENT("--(?!\\[=*\\[)","$"),e.COMMENT("--\\[=*\\[","\\]=*\\]",{contains:[t],relevance:10})];return{name:"Lua",keywords:{$pattern:e.UNDERSCORE_IDENT_RE,literal:"true false nil",keyword:"and break do else elseif end for goto if in local not or repeat return then until while",built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove"},contains:a.concat([{className:"function",beginKeywords:"function",end:"\\)",contains:[e.inherit(e.TITLE_MODE,{begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params",begin:"\\(",endsWithParent:!0,contains:a}].concat(a)},e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string",begin:"\\[=*\\[",end:"\\]=*\\]",contains:[t],relevance:5}])}}}()); +hljs.registerLanguage("makefile",function(){"use strict";return function(e){var i={className:"variable",variants:[{begin:"\\$\\("+e.UNDERSCORE_IDENT_RE+"\\)",contains:[e.BACKSLASH_ESCAPE]},{begin:/\$[@%`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin:"",relevance:10,contains:[a,i,t,s,{begin:"\\[",end:"\\]",contains:[{className:"meta",begin:"",contains:[a,s,i,t]}]}]},e.COMMENT("\x3c!--","--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",end:"\\]\\]>",relevance:10},n,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:")",end:">",keywords:{name:"style"},contains:[c],starts:{end:"",returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:")",end:">",keywords:{name:"script"},contains:[c],starts:{end:"<\/script>",returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:"",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},c]}]}}}()); +hljs.registerLanguage("markdown",function(){"use strict";return function(n){const e={begin:"<",end:">",subLanguage:"xml",relevance:0},a={begin:"\\[.+?\\][\\(\\[].*?[\\)\\]]",returnBegin:!0,contains:[{className:"string",begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0,relevance:0},{className:"link",begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}],relevance:10},i={className:"strong",contains:[],variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},s={className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{begin:/_(?!_)/,end:/_/,relevance:0}]};i.contains.push(s),s.contains.push(i);var c=[e,a];return i.contains=i.contains.concat(c),s.contains=s.contains.concat(c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:c=c.concat(i,s)},{begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",contains:c}]}]},e,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",end:"\\s+",excludeEnd:!0},i,s,{className:"quote",begin:"^>\\s+",contains:c,end:"$"},{className:"code",variants:[{begin:"(`{3,})(.|\\n)*?\\1`*[ ]*"},{begin:"(~{3,})(.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}}()); +hljs.registerLanguage("nginx",function(){"use strict";return function(e){var n={className:"variable",variants:[{begin:/\$\d+/},{begin:/\$\{/,end:/}/},{begin:"[\\$\\@]"+e.UNDERSCORE_IDENT_RE}]},a={endsWithParent:!0,keywords:{$pattern:"[a-z/_]+",literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},relevance:0,illegal:"=>",contains:[e.HASH_COMMENT_MODE,{className:"string",contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/}]},{begin:"([a-z]+):/",end:"\\s",endsWithParent:!0,excludeEnd:!0,contains:[n]},{className:"regexp",contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:"\\s\\^",end:"\\s|{|;",returnEnd:!0},{begin:"~\\*?\\s+",end:"\\s|{|;",returnEnd:!0},{begin:"\\*(\\.[a-z\\-]+)+"},{begin:"([a-z\\-]+\\.)+\\*"}]},{className:"number",begin:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{className:"number",begin:"\\b\\d+[kKmMgGdshdwy]*\\b",relevance:0},n]};return{name:"Nginx config",aliases:["nginxconf"],contains:[e.HASH_COMMENT_MODE,{begin:e.UNDERSCORE_IDENT_RE+"\\s+{",returnBegin:!0,end:"{",contains:[{className:"section",begin:e.UNDERSCORE_IDENT_RE}],relevance:0},{begin:e.UNDERSCORE_IDENT_RE+"\\s",end:";|{",returnBegin:!0,contains:[{className:"attribute",begin:e.UNDERSCORE_IDENT_RE,starts:a}],relevance:0}],illegal:"[^\\s\\}]"}}}()); +hljs.registerLanguage("objectivec",function(){"use strict";return function(e){var n=/[a-zA-Z@][a-zA-Z0-9_]*/,_={$pattern:n,keyword:"@interface @class @protocol @implementation"};return{name:"Objective-C",aliases:["mm","objc","obj-c"],keywords:{$pattern:n,keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},illegal:"/,end:/$/,illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"class",begin:"("+_.keyword.split(" ").join("|")+")\\b",end:"({|$)",excludeEnd:!0,keywords:_,contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"\\."+e.UNDERSCORE_IDENT_RE,relevance:0}]}}}()); +hljs.registerLanguage("perl",function(){"use strict";return function(e){var n={$pattern:/[\w.]+/,keyword:"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qq fileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmget sub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedir ioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when"},t={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:n},s={begin:"->{",end:"}"},r={variants:[{begin:/\$\d/},{begin:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{begin:/[\$%@][^\s\w{]/,relevance:0}]},i=[e.BACKSLASH_ESCAPE,t,r],a=[r,e.HASH_COMMENT_MODE,e.COMMENT("^\\=\\w","\\=cut",{endsWithParent:!0}),s,{className:"string",contains:i,variants:[{begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[",end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*\\<",end:"\\>",relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'",contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE]},{begin:"{\\w+}",contains:[],relevance:0},{begin:"-?\\w+\\s*\\=\\>",contains:[],relevance:0}]},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\/\\/|"+e.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*",keywords:"split return print reverse grep",relevance:0,contains:[e.HASH_COMMENT_MODE,{className:"regexp",begin:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",relevance:10},{className:"regexp",begin:"(m|qr)?/",end:"/[a-z]*",contains:[e.BACKSLASH_ESCAPE],relevance:0}]},{className:"function",beginKeywords:"sub",end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5,contains:[e.TITLE_MODE]},{begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$",end:"^__END__$",subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$",className:"comment"}]}];return t.contains=a,s.contains=a,{name:"Perl",aliases:["pl","pm"],keywords:n,contains:a}}}()); +hljs.registerLanguage("php",function(){"use strict";return function(e){var r={begin:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},t={className:"meta",variants:[{begin:/<\?php/,relevance:10},{begin:/<\?[=]?/},{begin:/\?>/}]},a={className:"string",contains:[e.BACKSLASH_ESCAPE,t],variants:[{begin:'b"',end:'"'},{begin:"b'",end:"'"},e.inherit(e.APOS_STRING_MODE,{illegal:null}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null})]},n={variants:[e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE]},i={keyword:"__CLASS__ __DIR__ __FILE__ __FUNCTION__ __LINE__ __METHOD__ __NAMESPACE__ __TRAIT__ die echo exit include include_once print require require_once array abstract and as binary bool boolean break callable case catch class clone const continue declare default do double else elseif empty enddeclare endfor endforeach endif endswitch endwhile eval extends final finally float for foreach from global goto if implements instanceof insteadof int integer interface isset iterable list new object or private protected public real return string switch throw trait try unset use var void while xor yield",literal:"false null true",built_in:"Error|0 AppendIterator ArgumentCountError ArithmeticError ArrayIterator ArrayObject AssertionError BadFunctionCallException BadMethodCallException CachingIterator CallbackFilterIterator CompileError Countable DirectoryIterator DivisionByZeroError DomainException EmptyIterator ErrorException Exception FilesystemIterator FilterIterator GlobIterator InfiniteIterator InvalidArgumentException IteratorIterator LengthException LimitIterator LogicException MultipleIterator NoRewindIterator OutOfBoundsException OutOfRangeException OuterIterator OverflowException ParentIterator ParseError RangeException RecursiveArrayIterator RecursiveCachingIterator RecursiveCallbackFilterIterator RecursiveDirectoryIterator RecursiveFilterIterator RecursiveIterator RecursiveIteratorIterator RecursiveRegexIterator RecursiveTreeIterator RegexIterator RuntimeException SeekableIterator SplDoublyLinkedList SplFileInfo SplFileObject SplFixedArray SplHeap SplMaxHeap SplMinHeap SplObjectStorage SplObserver SplObserver SplPriorityQueue SplQueue SplStack SplSubject SplSubject SplTempFileObject TypeError UnderflowException UnexpectedValueException ArrayAccess Closure Generator Iterator IteratorAggregate Serializable Throwable Traversable WeakReference Directory __PHP_Incomplete_Class parent php_user_filter self static stdClass"};return{aliases:["php","php3","php4","php5","php6","php7"],case_insensitive:!0,keywords:i,contains:[e.HASH_COMMENT_MODE,e.COMMENT("//","$",{contains:[t]}),e.COMMENT("/\\*","\\*/",{contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),e.COMMENT("__halt_compiler.+?;",!1,{endsWithParent:!0,keywords:"__halt_compiler"}),{className:"string",begin:/<<<['"]?\w+['"]?$/,end:/^\w+;?$/,contains:[e.BACKSLASH_ESCAPE,{className:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/,end:/\}/}]}]},t,{className:"keyword",begin:/\$this\b/},r,{begin:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{className:"function",beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0,illegal:"[$%\\[]",contains:[e.UNDERSCORE_TITLE_MODE,{className:"params",begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0,keywords:i,contains:["self",r,e.C_BLOCK_COMMENT_MODE,a,n]}]},{className:"class",beginKeywords:"class interface",end:"{",excludeEnd:!0,illegal:/[:\(\$"]/,contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"namespace",end:";",illegal:/[\.']/,contains:[e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"use",end:";",contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"=>"},a,n]}}}()); +hljs.registerLanguage("php-template",function(){"use strict";return function(n){return{name:"PHP template",subLanguage:"xml",contains:[{begin:/<\?(php|=)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"',end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},n.inherit(n.APOS_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0}),n.inherit(n.QUOTE_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0})]}]}}}()); +hljs.registerLanguage("plaintext",function(){"use strict";return function(t){return{name:"Plain text",aliases:["text","txt"],disableAutodetect:!0}}}()); +hljs.registerLanguage("properties",function(){"use strict";return function(e){var n="[ \\t\\f]*",t="("+n+"[:=]"+n+"|[ \\t\\f]+)",a="([^\\\\:= \\t\\f\\n]|\\\\.)+",s={end:t,relevance:0,starts:{className:"string",end:/$/,relevance:0,contains:[{begin:"\\\\\\n"}]}};return{name:".properties",case_insensitive:!0,illegal:/\S/,contains:[e.COMMENT("^\\s*[!#]","$"),{begin:"([^\\\\\\W:= \\t\\f\\n]|\\\\.)+"+t,returnBegin:!0,contains:[{className:"attr",begin:"([^\\\\\\W:= \\t\\f\\n]|\\\\.)+",endsParent:!0,relevance:0}],starts:s},{begin:a+t,returnBegin:!0,relevance:0,contains:[{className:"meta",begin:a,endsParent:!0,relevance:0}],starts:s},{className:"attr",relevance:0,begin:a+n+"$"}]}}}()); +hljs.registerLanguage("python",function(){"use strict";return function(e){var n={keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10",built_in:"Ellipsis NotImplemented",literal:"False None True"},a={className:"meta",begin:/^(>>>|\.\.\.) /},i={className:"subst",begin:/\{/,end:/\}/,keywords:n,illegal:/#/},s={begin:/\{\{/,relevance:0},r={className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:/(u|b)?r?'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{begin:/(u|b)?r?"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{begin:/(fr|rf|f)'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,a,s,i]},{begin:/(fr|rf|f)"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,a,s,i]},{begin:/(u|r|ur)'/,end:/'/,relevance:10},{begin:/(u|r|ur)"/,end:/"/,relevance:10},{begin:/(b|br)'/,end:/'/},{begin:/(b|br)"/,end:/"/},{begin:/(fr|rf|f)'/,end:/'/,contains:[e.BACKSLASH_ESCAPE,s,i]},{begin:/(fr|rf|f)"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,i]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},l={className:"number",relevance:0,variants:[{begin:e.BINARY_NUMBER_RE+"[lLjJ]?"},{begin:"\\b(0o[0-7]+)[lLjJ]?"},{begin:e.C_NUMBER_RE+"[lLjJ]?"}]},t={className:"params",variants:[{begin:/\(\s*\)/,skip:!0,className:null},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:["self",a,l,r,e.HASH_COMMENT_MODE]}]};return i.contains=[r,l,a],{name:"Python",aliases:["py","gyp","ipython"],keywords:n,illegal:/(<\/|->|\?)|=>/,contains:[a,l,{beginKeywords:"if",relevance:0},r,e.HASH_COMMENT_MODE,{variants:[{className:"function",beginKeywords:"def"},{className:"class",beginKeywords:"class"}],end:/:/,illegal:/[${=;\n,]/,contains:[e.UNDERSCORE_TITLE_MODE,t,{begin:/->/,endsWithParent:!0,keywords:"None"}]},{className:"meta",begin:/^[\t ]*@/,end:/$/},{begin:/\b(print|exec)\(/}]}}}()); +hljs.registerLanguage("python-repl",function(){"use strict";return function(n){return{aliases:["pycon"],contains:[{className:"meta",starts:{end:/ |$/,starts:{end:"$",subLanguage:"python"}},variants:[{begin:/^>>>(?=[ ]|$)/},{begin:/^\.\.\.(?=[ ]|$)/}]}]}}}()); +hljs.registerLanguage("ruby",function(){"use strict";return function(e){var n="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",a={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},s={className:"doctag",begin:"@[A-Za-z]+"},i={begin:"#<",end:">"},r=[e.COMMENT("#","$",{contains:[s]}),e.COMMENT("^\\=begin","^\\=end",{contains:[s],relevance:10}),e.COMMENT("^__END__","\\n$")],c={className:"subst",begin:"#\\{",end:"}",keywords:a},t={className:"string",contains:[e.BACKSLASH_ESCAPE,c],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",end:">"},{begin:"%[qQwWx]?/",end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{begin:"%[qQwWx]?\\|",end:"\\|"},{begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{begin:/<<[-~]?'?(\w+)(?:.|\n)*?\n\s*\1\b/,returnBegin:!0,contains:[{begin:/<<[-~]?'?/},e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,contains:[e.BACKSLASH_ESCAPE,c]})]}]},b={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:a},d=[t,i,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,contains:[e.inherit(e.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<\\s*",contains:[{begin:"("+e.IDENT_RE+"::)?"+e.IDENT_RE}]}].concat(r)},{className:"function",beginKeywords:"def",end:"$|;",contains:[e.inherit(e.TITLE_MODE,{begin:n}),b].concat(r)},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[t,{begin:n}],relevance:0},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",begin:/\|/,end:/\|/,keywords:a},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[i,{className:"regexp",contains:[e.BACKSLASH_ESCAPE,c],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(r),relevance:0}].concat(r);c.contains=d,b.contains=d;var g=[{begin:/^\s*=>/,starts:{end:"$",contains:d}},{className:"meta",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",starts:{end:"$",contains:d}}];return{name:"Ruby",aliases:["rb","gemspec","podspec","thor","irb"],keywords:a,illegal:/\/\*/,contains:r.concat(g).concat(d)}}}()); +hljs.registerLanguage("rust",function(){"use strict";return function(e){var n="([ui](8|16|32|64|128|size)|f(32|64))?",t="drop i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 str char bool Box Option Result String Vec Copy Send Sized Sync Drop Fn FnMut FnOnce ToOwned Clone Debug PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator SliceConcatExt ToString assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules! assert_ne! debug_assert_ne!";return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?",keyword:"abstract as async await become box break const continue crate do dyn else enum extern false final fn for if impl in let loop macro match mod move mut override priv pub ref return self Self static struct super trait true try type typeof unsafe unsized use virtual where while yield",literal:"true false Some None Ok Err",built_in:t},illegal:""}]}}}()); +hljs.registerLanguage("scss",function(){"use strict";return function(e){var t={className:"variable",begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b"},i={className:"number",begin:"#[0-9A-Fa-f]+"};return e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{name:"SCSS",case_insensitive:!0,illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:"\\#[A-Za-z0-9_-]+",relevance:0},{className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0},{className:"selector-attr",begin:"\\[",end:"\\]",illegal:"$"},{className:"selector-tag",begin:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b",relevance:0},{className:"selector-pseudo",begin:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)"},{className:"selector-pseudo",begin:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)"},t,{className:"attribute",begin:"\\b(src|z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b",illegal:"[^\\s]"},{begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{begin:":",end:";",contains:[t,i,e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{className:"meta",begin:"!important"}]},{begin:"@(page|font-face)",lexemes:"@[a-z-]+",keywords:"@page @font-face"},{begin:"@",end:"[{;]",returnBegin:!0,keywords:"and or not only",contains:[{begin:"@[a-z-]+",className:"keyword"},t,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,i,e.CSS_NUMBER_MODE]}]}}}()); +hljs.registerLanguage("shell",function(){"use strict";return function(s){return{name:"Shell Session",aliases:["console"],contains:[{className:"meta",begin:"^\\s{0,3}[/\\w\\d\\[\\]()@-]*[>%$#]",starts:{end:"$",subLanguage:"bash"}}]}}}()); +hljs.registerLanguage("sql",function(){"use strict";return function(e){var t=e.COMMENT("--","$");return{name:"SQL",case_insensitive:!0,illegal:/[<>{}*]/,contains:[{beginKeywords:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment values with",end:/;/,endsWithParent:!0,keywords:{$pattern:/[\w\.]+/,keyword:"as abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias all allocate allow alter always analyze ancillary and anti any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound bucket buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain explode export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force foreign form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour hours http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lateral lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minutes minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notnull notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second seconds section securefile security seed segment select self semi sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tablesample tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unnest unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace window with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null unknown",built_in:"array bigint binary bit blob bool boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text time timestamp tinyint varchar varchar2 varying void"},contains:[{className:"string",begin:"'",end:"'",contains:[{begin:"''"}]},{className:"string",begin:'"',end:'"',contains:[{begin:'""'}]},{className:"string",begin:"`",end:"`"},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t,e.HASH_COMMENT_MODE]},e.C_BLOCK_COMMENT_MODE,t,e.HASH_COMMENT_MODE]}}}()); +hljs.registerLanguage("swift",function(){"use strict";return function(e){var i={keyword:"#available #colorLiteral #column #else #elseif #endif #file #fileLiteral #function #if #imageLiteral #line #selector #sourceLocation _ __COLUMN__ __FILE__ __FUNCTION__ __LINE__ Any as as! as? associatedtype associativity break case catch class continue convenience default defer deinit didSet do dynamic dynamicType else enum extension fallthrough false fileprivate final for func get guard if import in indirect infix init inout internal is lazy left let mutating nil none nonmutating open operator optional override postfix precedence prefix private protocol Protocol public repeat required rethrows return right self Self set static struct subscript super switch throw throws true try try! try? Type typealias unowned var weak where while willSet",literal:"true false nil",built_in:"abs advance alignof alignofValue anyGenerator assert assertionFailure bridgeFromObjectiveC bridgeFromObjectiveCUnconditional bridgeToObjectiveC bridgeToObjectiveCUnconditional c compactMap contains count countElements countLeadingZeros debugPrint debugPrintln distance dropFirst dropLast dump encodeBitsAsWords enumerate equal fatalError filter find getBridgedObjectiveCType getVaList indices insertionSort isBridgedToObjectiveC isBridgedVerbatimToObjectiveC isUniquelyReferenced isUniquelyReferencedNonObjC join lazy lexicographicalCompare map max maxElement min minElement numericCast overlaps partition posix precondition preconditionFailure print println quickSort readLine reduce reflect reinterpretCast reverse roundUpToAlignment sizeof sizeofValue sort split startsWith stride strideof strideofValue swap toString transcode underestimateCount unsafeAddressOf unsafeBitCast unsafeDowncast unsafeUnwrap unsafeReflect withExtendedLifetime withObjectAtPlusZero withUnsafePointer withUnsafePointerToObject withUnsafeMutablePointer withUnsafeMutablePointers withUnsafePointer withUnsafePointers withVaList zip"},n=e.COMMENT("/\\*","\\*/",{contains:["self"]}),t={className:"subst",begin:/\\\(/,end:"\\)",keywords:i,contains:[]},a={className:"string",contains:[e.BACKSLASH_ESCAPE,t],variants:[{begin:/"""/,end:/"""/},{begin:/"/,end:/"/}]},r={className:"number",begin:"\\b([\\d_]+(\\.[\\deE_]+)?|0x[a-fA-F0-9_]+(\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\b",relevance:0};return t.contains=[r],{name:"Swift",keywords:i,contains:[a,e.C_LINE_COMMENT_MODE,n,{className:"type",begin:"\\b[A-Z][\\wÀ-ʸ']*[!?]"},{className:"type",begin:"\\b[A-Z][\\wÀ-ʸ']*",relevance:0},r,{className:"function",beginKeywords:"func",end:"{",excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{begin://},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:i,contains:["self",r,a,e.C_BLOCK_COMMENT_MODE,{begin:":"}],illegal:/["']/}],illegal:/\[|%/},{className:"class",beginKeywords:"struct protocol class extension enum",keywords:i,end:"\\{",excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/})]},{className:"meta",begin:"(@discardableResult|@warn_unused_result|@exported|@lazy|@noescape|@NSCopying|@NSManaged|@objc|@objcMembers|@convention|@required|@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|@infix|@prefix|@postfix|@autoclosure|@testable|@available|@nonobjc|@NSApplicationMain|@UIApplicationMain|@dynamicMemberLookup|@propertyWrapper)\\b"},{beginKeywords:"import",end:/$/,contains:[e.C_LINE_COMMENT_MODE,n]}]}}}()); +hljs.registerLanguage("typescript",function(){"use strict";const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);return function(r){var t={$pattern:"[A-Za-z$_][0-9A-Za-z$_]*",keyword:e.concat(["type","namespace","typedef","interface","public","private","protected","implements","declare","abstract","readonly"]).join(" "),literal:n.join(" "),built_in:a.concat(["any","void","number","boolean","string","object","never","enum"]).join(" ")},s={className:"meta",begin:"@[A-Za-z$_][0-9A-Za-z$_]*"},i={className:"number",variants:[{begin:"\\b(0[bB][01]+)n?"},{begin:"\\b(0[oO][0-7]+)n?"},{begin:r.C_NUMBER_RE+"n?"}],relevance:0},o={className:"subst",begin:"\\$\\{",end:"\\}",keywords:t,contains:[]},c={begin:"html`",end:"",starts:{end:"`",returnEnd:!1,contains:[r.BACKSLASH_ESCAPE,o],subLanguage:"xml"}},l={begin:"css`",end:"",starts:{end:"`",returnEnd:!1,contains:[r.BACKSLASH_ESCAPE,o],subLanguage:"css"}},E={className:"string",begin:"`",end:"`",contains:[r.BACKSLASH_ESCAPE,o]};o.contains=[r.APOS_STRING_MODE,r.QUOTE_STRING_MODE,c,l,E,i,r.REGEXP_MODE];var d={begin:"\\(",end:/\)/,keywords:t,contains:["self",r.QUOTE_STRING_MODE,r.APOS_STRING_MODE,r.NUMBER_MODE]},u={className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:t,contains:[r.C_LINE_COMMENT_MODE,r.C_BLOCK_COMMENT_MODE,s,d]};return{name:"TypeScript",aliases:["ts"],keywords:t,contains:[r.SHEBANG(),{className:"meta",begin:/^\s*['"]use strict['"]/},r.APOS_STRING_MODE,r.QUOTE_STRING_MODE,c,l,E,r.C_LINE_COMMENT_MODE,r.C_BLOCK_COMMENT_MODE,i,{begin:"("+r.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[r.C_LINE_COMMENT_MODE,r.C_BLOCK_COMMENT_MODE,r.REGEXP_MODE,{className:"function",begin:"(\\([^(]*(\\([^(]*(\\([^(]*\\))?\\))?\\)|"+r.UNDERSCORE_IDENT_RE+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:r.UNDERSCORE_IDENT_RE},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:t,contains:d.contains}]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/[\{;]/,excludeEnd:!0,keywords:t,contains:["self",r.inherit(r.TITLE_MODE,{begin:"[A-Za-z$_][0-9A-Za-z$_]*"}),u],illegal:/%/,relevance:0},{beginKeywords:"constructor",end:/[\{;]/,excludeEnd:!0,contains:["self",u]},{begin:/module\./,keywords:{built_in:"module"},relevance:0},{beginKeywords:"module",end:/\{/,excludeEnd:!0},{beginKeywords:"interface",end:/\{/,excludeEnd:!0,keywords:"interface extends"},{begin:/\$[(.]/},{begin:"\\."+r.IDENT_RE,relevance:0},s,d]}}}()); +hljs.registerLanguage("yaml",function(){"use strict";return function(e){var n="true false yes no null",a="[\\w#;/?:@&=+$,.~*\\'()[\\]]+",s={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:"{{",end:"}}"},{begin:"%{",end:"}"}]}]},i=e.inherit(s,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={end:",",endsWithParent:!0,excludeEnd:!0,contains:[],keywords:n,relevance:0},t={begin:"{",end:"}",contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[",end:"\\]",contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---s*$",relevance:10},{className:"string",begin:"[\\|>]([0-9]?[+-])?[ ]*\\n( *)[\\S ]+\\n(\\2[\\S ]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type",begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"\\-(?=[ ]|$)",relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},{className:"number",begin:e.C_NUMBER_RE+"\\b"},t,g,s],c=[...b];return c.pop(),c.push(i),l.contains=c,{name:"YAML",case_insensitive:!0,aliases:["yml","YAML"],contains:b}}}()); +hljs.registerLanguage("armasm",function(){"use strict";return function(s){const e={variants:[s.COMMENT("^[ \\t]*(?=#)","$",{relevance:0,excludeBegin:!0}),s.COMMENT("[;@]","$",{relevance:0}),s.C_LINE_COMMENT_MODE,s.C_BLOCK_COMMENT_MODE]};return{name:"ARM Assembly",case_insensitive:!0,aliases:["arm"],keywords:{$pattern:"\\.?"+s.IDENT_RE,meta:".2byte .4byte .align .ascii .asciz .balign .byte .code .data .else .end .endif .endm .endr .equ .err .exitm .extern .global .hword .if .ifdef .ifndef .include .irp .long .macro .rept .req .section .set .skip .space .text .word .arm .thumb .code16 .code32 .force_thumb .thumb_func .ltorg ALIAS ALIGN ARM AREA ASSERT ATTR CN CODE CODE16 CODE32 COMMON CP DATA DCB DCD DCDU DCDO DCFD DCFDU DCI DCQ DCQU DCW DCWU DN ELIF ELSE END ENDFUNC ENDIF ENDP ENTRY EQU EXPORT EXPORTAS EXTERN FIELD FILL FUNCTION GBLA GBLL GBLS GET GLOBAL IF IMPORT INCBIN INCLUDE INFO KEEP LCLA LCLL LCLS LTORG MACRO MAP MEND MEXIT NOFP OPT PRESERVE8 PROC QN READONLY RELOC REQUIRE REQUIRE8 RLIST FN ROUT SETA SETL SETS SN SPACE SUBT THUMB THUMBX TTL WHILE WEND ",built_in:"r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 pc lr sp ip sl sb fp a1 a2 a3 a4 v1 v2 v3 v4 v5 v6 v7 v8 f0 f1 f2 f3 f4 f5 f6 f7 p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 cpsr_c cpsr_x cpsr_s cpsr_f cpsr_cx cpsr_cxs cpsr_xs cpsr_xsf cpsr_sf cpsr_cxsf spsr_c spsr_x spsr_s spsr_f spsr_cx spsr_cxs spsr_xs spsr_xsf spsr_sf spsr_cxsf s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 s16 s17 s18 s19 s20 s21 s22 s23 s24 s25 s26 s27 s28 s29 s30 s31 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 {PC} {VAR} {TRUE} {FALSE} {OPT} {CONFIG} {ENDIAN} {CODESIZE} {CPU} {FPU} {ARCHITECTURE} {PCSTOREOFFSET} {ARMASM_VERSION} {INTER} {ROPI} {RWPI} {SWST} {NOSWST} . @"},contains:[{className:"keyword",begin:"\\b(adc|(qd?|sh?|u[qh]?)?add(8|16)?|usada?8|(q|sh?|u[qh]?)?(as|sa)x|and|adrl?|sbc|rs[bc]|asr|b[lx]?|blx|bxj|cbn?z|tb[bh]|bic|bfc|bfi|[su]bfx|bkpt|cdp2?|clz|clrex|cmp|cmn|cpsi[ed]|cps|setend|dbg|dmb|dsb|eor|isb|it[te]{0,3}|lsl|lsr|ror|rrx|ldm(([id][ab])|f[ds])?|ldr((s|ex)?[bhd])?|movt?|mvn|mra|mar|mul|[us]mull|smul[bwt][bt]|smu[as]d|smmul|smmla|mla|umlaal|smlal?([wbt][bt]|d)|mls|smlsl?[ds]|smc|svc|sev|mia([bt]{2}|ph)?|mrr?c2?|mcrr2?|mrs|msr|orr|orn|pkh(tb|bt)|rbit|rev(16|sh)?|sel|[su]sat(16)?|nop|pop|push|rfe([id][ab])?|stm([id][ab])?|str(ex)?[bhd]?|(qd?)?sub|(sh?|q|u[qh]?)?sub(8|16)|[su]xt(a?h|a?b(16)?)|srs([id][ab])?|swpb?|swi|smi|tst|teq|wfe|wfi|yield)(eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo)?[sptrx]?(?=\\s)"},e,s.QUOTE_STRING_MODE,{className:"string",begin:"'",end:"[^\\\\]'",relevance:0},{className:"title",begin:"\\|",end:"\\|",illegal:"\\n",relevance:0},{className:"number",variants:[{begin:"[#$=]?0x[0-9a-f]+"},{begin:"[#$=]?0b[01]+"},{begin:"[#$=]\\d+"},{begin:"\\b\\d+"}],relevance:0},{className:"symbol",variants:[{begin:"^[ \\t]*[a-z_\\.\\$][a-z0-9_\\.\\$]+:"},{begin:"^[a-z_\\.\\$][a-z0-9_\\.\\$]+"},{begin:"[=#]\\w+"}],relevance:0}]}}}()); +hljs.registerLanguage("d",function(){"use strict";return function(e){var a={$pattern:e.UNDERSCORE_IDENT_RE,keyword:"abstract alias align asm assert auto body break byte case cast catch class const continue debug default delete deprecated do else enum export extern final finally for foreach foreach_reverse|10 goto if immutable import in inout int interface invariant is lazy macro mixin module new nothrow out override package pragma private protected public pure ref return scope shared static struct super switch synchronized template this throw try typedef typeid typeof union unittest version void volatile while with __FILE__ __LINE__ __gshared|10 __thread __traits __DATE__ __EOF__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__",built_in:"bool cdouble cent cfloat char creal dchar delegate double dstring float function idouble ifloat ireal long real short string ubyte ucent uint ulong ushort wchar wstring",literal:"false null true"},d="((0|[1-9][\\d_]*)|0[bB][01_]+|0[xX]([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*))",n="\\\\(['\"\\?\\\\abfnrtv]|u[\\dA-Fa-f]{4}|[0-7]{1,3}|x[\\dA-Fa-f]{2}|U[\\dA-Fa-f]{8})|&[a-zA-Z\\d]{2,};",t={className:"number",begin:"\\b"+d+"(L|u|U|Lu|LU|uL|UL)?",relevance:0},_={className:"number",begin:"\\b(((0[xX](([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*)\\.([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*)|\\.?([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*))[pP][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d))|((0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)(\\.\\d*|([eE][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)))|\\d+\\.(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)|\\.(0|[1-9][\\d_]*)([eE][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d))?))([fF]|L|i|[fF]i|Li)?|"+d+"(i|[fF]i|Li))",relevance:0},r={className:"string",begin:"'("+n+"|.)",end:"'",illegal:"."},i={className:"string",begin:'"',contains:[{begin:n,relevance:0}],end:'"[cwd]?'},s=e.COMMENT("\\/\\+","\\+\\/",{contains:["self"],relevance:10});return{name:"D",keywords:a,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s,{className:"string",begin:'x"[\\da-fA-F\\s\\n\\r]*"[cwd]?',relevance:10},i,{className:"string",begin:'[rq]"',end:'"[cwd]?',relevance:5},{className:"string",begin:"`",end:"`[cwd]?"},{className:"string",begin:'q"\\{',end:'\\}"'},_,t,r,{className:"meta",begin:"^#!",end:"$",relevance:5},{className:"meta",begin:"#(line)",end:"$",relevance:5},{className:"keyword",begin:"@[a-zA-Z_][a-zA-Z_\\d]*"}]}}}()); +hljs.registerLanguage("handlebars",function(){"use strict";function e(...e){return e.map(e=>(function(e){return e?"string"==typeof e?e:e.source:null})(e)).join("")}return function(n){const a={"builtin-name":"action bindattr collection component concat debugger each each-in get hash if in input link-to loc log lookup mut outlet partial query-params render template textarea unbound unless view with yield"},t=/\[.*?\]/,s=/[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+/,i=e("(",/'.*?'/,"|",/".*?"/,"|",t,"|",s,"|",/\.|\//,")+"),r=e("(",t,"|",s,")(?==)"),l={begin:i,lexemes:/[\w.\/]+/},c=n.inherit(l,{keywords:{literal:"true false undefined null"}}),o={begin:/\(/,end:/\)/},m={className:"attr",begin:r,relevance:0,starts:{begin:/=/,end:/=/,starts:{contains:[n.NUMBER_MODE,n.QUOTE_STRING_MODE,n.APOS_STRING_MODE,c,o]}}},d={contains:[n.NUMBER_MODE,n.QUOTE_STRING_MODE,n.APOS_STRING_MODE,{begin:/as\s+\|/,keywords:{keyword:"as"},end:/\|/,contains:[{begin:/\w+/}]},m,c,o],returnEnd:!0},g=n.inherit(l,{className:"name",keywords:a,starts:n.inherit(d,{end:/\)/})});o.contains=[g];const u=n.inherit(l,{keywords:a,className:"name",starts:n.inherit(d,{end:/}}/})}),b=n.inherit(l,{keywords:a,className:"name"}),h=n.inherit(l,{className:"name",keywords:a,starts:n.inherit(d,{end:/}}/})});return{name:"Handlebars",aliases:["hbs","html.hbs","html.handlebars","htmlbars"],case_insensitive:!0,subLanguage:"xml",contains:[{begin:/\\\{\{/,skip:!0},{begin:/\\\\(?=\{\{)/,skip:!0},n.COMMENT(/\{\{!--/,/--\}\}/),n.COMMENT(/\{\{!/,/\}\}/),{className:"template-tag",begin:/\{\{\{\{(?!\/)/,end:/\}\}\}\}/,contains:[u],starts:{end:/\{\{\{\{\//,returnEnd:!0,subLanguage:"xml"}},{className:"template-tag",begin:/\{\{\{\{\//,end:/\}\}\}\}/,contains:[b]},{className:"template-tag",begin:/\{\{#/,end:/\}\}/,contains:[u]},{className:"template-tag",begin:/\{\{(?=else\}\})/,end:/\}\}/,keywords:"else"},{className:"template-tag",begin:/\{\{\//,end:/\}\}/,contains:[b]},{className:"template-variable",begin:/\{\{\{/,end:/\}\}\}/,contains:[h]},{className:"template-variable",begin:/\{\{/,end:/\}\}/,contains:[h]}]}}}()); +hljs.registerLanguage("haskell",function(){"use strict";return function(e){var n={variants:[e.COMMENT("--","$"),e.COMMENT("{-","-}",{contains:["self"]})]},i={className:"meta",begin:"{-#",end:"#-}"},a={className:"meta",begin:"^#",end:"$"},s={className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},l={begin:"\\(",end:"\\)",illegal:'"',contains:[i,a,{className:"type",begin:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},e.inherit(e.TITLE_MODE,{begin:"[_a-z][\\w']*"}),n]};return{name:"Haskell",aliases:["hs"],keywords:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",contains:[{beginKeywords:"module",end:"where",keywords:"module where",contains:[l,n],illegal:"\\W\\.|;"},{begin:"\\bimport\\b",end:"$",keywords:"import qualified as hiding",contains:[l,n],illegal:"\\W\\.|;"},{className:"class",begin:"^(\\s*)?(class|instance)\\b",end:"where",keywords:"class family instance where",contains:[s,l,n]},{className:"class",begin:"\\b(data|(new)?type)\\b",end:"$",keywords:"data family type newtype deriving",contains:[i,s,l,{begin:"{",end:"}",contains:l.contains},n]},{beginKeywords:"default",end:"$",contains:[s,l,n]},{beginKeywords:"infix infixl infixr",end:"$",contains:[e.C_NUMBER_MODE,n]},{begin:"\\bforeign\\b",end:"$",keywords:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",contains:[s,e.QUOTE_STRING_MODE,n]},{className:"meta",begin:"#!\\/usr\\/bin\\/env runhaskell",end:"$"},i,a,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,s,e.inherit(e.TITLE_MODE,{begin:"^[_a-z][\\w']*"}),n,{begin:"->|<-"}]}}}()); +hljs.registerLanguage("julia",function(){"use strict";return function(e){var r="[A-Za-z_\\u00A1-\\uFFFF][A-Za-z_0-9\\u00A1-\\uFFFF]*",t={$pattern:r,keyword:"in isa where baremodule begin break catch ccall const continue do else elseif end export false finally for function global if import importall let local macro module quote return true try using while type immutable abstract bitstype typealias ",literal:"true false ARGS C_NULL DevNull ENDIAN_BOM ENV I Inf Inf16 Inf32 Inf64 InsertionSort JULIA_HOME LOAD_PATH MergeSort NaN NaN16 NaN32 NaN64 PROGRAM_FILE QuickSort RoundDown RoundFromZero RoundNearest RoundNearestTiesAway RoundNearestTiesUp RoundToZero RoundUp STDERR STDIN STDOUT VERSION catalan e|0 eu|0 eulergamma golden im nothing pi γ π φ ",built_in:"ANY AbstractArray AbstractChannel AbstractFloat AbstractMatrix AbstractRNG AbstractSerializer AbstractSet AbstractSparseArray AbstractSparseMatrix AbstractSparseVector AbstractString AbstractUnitRange AbstractVecOrMat AbstractVector Any ArgumentError Array AssertionError Associative Base64DecodePipe Base64EncodePipe Bidiagonal BigFloat BigInt BitArray BitMatrix BitVector Bool BoundsError BufferStream CachingPool CapturedException CartesianIndex CartesianRange Cchar Cdouble Cfloat Channel Char Cint Cintmax_t Clong Clonglong ClusterManager Cmd CodeInfo Colon Complex Complex128 Complex32 Complex64 CompositeException Condition ConjArray ConjMatrix ConjVector Cptrdiff_t Cshort Csize_t Cssize_t Cstring Cuchar Cuint Cuintmax_t Culong Culonglong Cushort Cwchar_t Cwstring DataType Date DateFormat DateTime DenseArray DenseMatrix DenseVecOrMat DenseVector Diagonal Dict DimensionMismatch Dims DirectIndexString Display DivideError DomainError EOFError EachLine Enum Enumerate ErrorException Exception ExponentialBackOff Expr Factorization FileMonitor Float16 Float32 Float64 Function Future GlobalRef GotoNode HTML Hermitian IO IOBuffer IOContext IOStream IPAddr IPv4 IPv6 IndexCartesian IndexLinear IndexStyle InexactError InitError Int Int128 Int16 Int32 Int64 Int8 IntSet Integer InterruptException InvalidStateException Irrational KeyError LabelNode LinSpace LineNumberNode LoadError LowerTriangular MIME Matrix MersenneTwister Method MethodError MethodTable Module NTuple NewvarNode NullException Nullable Number ObjectIdDict OrdinalRange OutOfMemoryError OverflowError Pair ParseError PartialQuickSort PermutedDimsArray Pipe PollingFileWatcher ProcessExitedException Ptr QuoteNode RandomDevice Range RangeIndex Rational RawFD ReadOnlyMemoryError Real ReentrantLock Ref Regex RegexMatch RemoteChannel RemoteException RevString RoundingMode RowVector SSAValue SegmentationFault SerializationState Set SharedArray SharedMatrix SharedVector Signed SimpleVector Slot SlotNumber SparseMatrixCSC SparseVector StackFrame StackOverflowError StackTrace StepRange StepRangeLen StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray SubString SymTridiagonal Symbol Symmetric SystemError TCPSocket Task Text TextDisplay Timer Tridiagonal Tuple Type TypeError TypeMapEntry TypeMapLevel TypeName TypeVar TypedSlot UDPSocket UInt UInt128 UInt16 UInt32 UInt64 UInt8 UndefRefError UndefVarError UnicodeError UniformScaling Union UnionAll UnitRange Unsigned UpperTriangular Val Vararg VecElement VecOrMat Vector VersionNumber Void WeakKeyDict WeakRef WorkerConfig WorkerPool "},a={keywords:t,illegal:/<\//},n={className:"subst",begin:/\$\(/,end:/\)/,keywords:t},o={className:"variable",begin:"\\$"+r},i={className:"string",contains:[e.BACKSLASH_ESCAPE,n,o],variants:[{begin:/\w*"""/,end:/"""\w*/,relevance:10},{begin:/\w*"/,end:/"\w*/}]},l={className:"string",contains:[e.BACKSLASH_ESCAPE,n,o],begin:"`",end:"`"},s={className:"meta",begin:"@"+r};return a.name="Julia",a.contains=[{className:"number",begin:/(\b0x[\d_]*(\.[\d_]*)?|0x\.\d[\d_]*)p[-+]?\d+|\b0[box][a-fA-F0-9][a-fA-F0-9_]*|(\b\d[\d_]*(\.[\d_]*)?|\.\d[\d_]*)([eEfF][-+]?\d+)?/,relevance:0},{className:"string",begin:/'(.|\\[xXuU][a-zA-Z0-9]+)'/},i,l,s,{className:"comment",variants:[{begin:"#=",end:"=#",relevance:10},{begin:"#",end:"$"}]},e.HASH_COMMENT_MODE,{className:"keyword",begin:"\\b(((abstract|primitive)\\s+)type|(mutable\\s+)?struct)\\b"},{begin:/<:/}],n.contains=a.contains,a}}()); +hljs.registerLanguage("nim",function(){"use strict";return function(e){return{name:"Nim",aliases:["nim"],keywords:{keyword:"addr and as asm bind block break case cast const continue converter discard distinct div do elif else end enum except export finally for from func generic if import in include interface is isnot iterator let macro method mixin mod nil not notin object of or out proc ptr raise ref return shl shr static template try tuple type using var when while with without xor yield",literal:"shared guarded stdin stdout stderr result true false",built_in:"int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 float float32 float64 bool char string cstring pointer expr stmt void auto any range array openarray varargs seq set clong culong cchar cschar cshort cint csize clonglong cfloat cdouble clongdouble cuchar cushort cuint culonglong cstringarray semistatic"},contains:[{className:"meta",begin:/{\./,end:/\.}/,relevance:10},{className:"string",begin:/[a-zA-Z]\w*"/,end:/"/,contains:[{begin:/""/}]},{className:"string",begin:/([a-zA-Z]\w*)?"""/,end:/"""/},e.QUOTE_STRING_MODE,{className:"type",begin:/\b[A-Z]\w+\b/,relevance:0},{className:"number",relevance:0,variants:[{begin:/\b(0[xX][0-9a-fA-F][_0-9a-fA-F]*)('?[iIuU](8|16|32|64))?/},{begin:/\b(0o[0-7][_0-7]*)('?[iIuUfF](8|16|32|64))?/},{begin:/\b(0(b|B)[01][_01]*)('?[iIuUfF](8|16|32|64))?/},{begin:/\b(\d[_\d]*)('?[iIuUfF](8|16|32|64))?/}]},e.HASH_COMMENT_MODE]}}}()); +hljs.registerLanguage("nix",function(){"use strict";return function(e){var n={keyword:"rec with let in inherit assert if else then",literal:"true false or and null",built_in:"import abort baseNameOf dirOf isNull builtins map removeAttrs throw toString derivation"},i={className:"subst",begin:/\$\{/,end:/}/,keywords:n},t={className:"string",contains:[i],variants:[{begin:"''",end:"''"},{begin:'"',end:'"'}]},s=[e.NUMBER_MODE,e.HASH_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,t,{begin:/[a-zA-Z0-9-_]+(\s*=)/,returnBegin:!0,relevance:0,contains:[{className:"attr",begin:/\S+/}]}];return i.contains=s,{name:"Nix",aliases:["nixos"],keywords:n,contains:s}}}()); +hljs.registerLanguage("r",function(){"use strict";return function(e){var n="([a-zA-Z]|\\.[a-zA-Z.])[a-zA-Z0-9._]*";return{name:"R",contains:[e.HASH_COMMENT_MODE,{begin:n,keywords:{$pattern:n,keyword:"function if in break next repeat else for return switch while try tryCatch stop warning require library attach detach source setMethod setGeneric setGroupGeneric setClass ...",literal:"NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10"},relevance:0},{className:"number",begin:"0[xX][0-9a-fA-F]+[Li]?\\b",relevance:0},{className:"number",begin:"\\d+(?:[eE][+\\-]?\\d*)?L\\b",relevance:0},{className:"number",begin:"\\d+\\.(?!\\d)(?:i\\b)?",relevance:0},{className:"number",begin:"\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b",relevance:0},{className:"number",begin:"\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b",relevance:0},{begin:"`",end:"`",relevance:0},{className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:'"',end:'"'},{begin:"'",end:"'"}]}]}}}()); +hljs.registerLanguage("scala",function(){"use strict";return function(e){var n={className:"subst",variants:[{begin:"\\$[A-Za-z0-9_]+"},{begin:"\\${",end:"}"}]},a={className:"string",variants:[{begin:'"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:'"""',end:'"""',relevance:10},{begin:'[a-z]+"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE,n]},{className:"string",begin:'[a-z]+"""',end:'"""',contains:[n],relevance:10}]},s={className:"type",begin:"\\b[A-Z][A-Za-z0-9_]*",relevance:0},t={className:"title",begin:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/,relevance:0},i={className:"class",beginKeywords:"class object trait type",end:/[:={\[\n;]/,excludeEnd:!0,contains:[{beginKeywords:"extends with",relevance:10},{begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[s]},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[s]},t]},l={className:"function",beginKeywords:"def",end:/[:={\[(\n;]/,excludeEnd:!0,contains:[t]};return{name:"Scala",keywords:{literal:"true false null",keyword:"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit"},contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,{className:"symbol",begin:"'\\w[\\w\\d_]*(?!')"},s,l,i,e.C_NUMBER_MODE,{className:"meta",begin:"@[A-Za-z]+"}]}}}()); +hljs.registerLanguage("x86asm",function(){"use strict";return function(s){return{name:"Intel x86 Assembly",case_insensitive:!0,keywords:{$pattern:"[.%]?"+s.IDENT_RE,keyword:"lock rep repe repz repne repnz xaquire xrelease bnd nobnd aaa aad aam aas adc add and arpl bb0_reset bb1_reset bound bsf bsr bswap bt btc btr bts call cbw cdq cdqe clc cld cli clts cmc cmp cmpsb cmpsd cmpsq cmpsw cmpxchg cmpxchg486 cmpxchg8b cmpxchg16b cpuid cpu_read cpu_write cqo cwd cwde daa das dec div dmint emms enter equ f2xm1 fabs fadd faddp fbld fbstp fchs fclex fcmovb fcmovbe fcmove fcmovnb fcmovnbe fcmovne fcmovnu fcmovu fcom fcomi fcomip fcomp fcompp fcos fdecstp fdisi fdiv fdivp fdivr fdivrp femms feni ffree ffreep fiadd ficom ficomp fidiv fidivr fild fimul fincstp finit fist fistp fisttp fisub fisubr fld fld1 fldcw fldenv fldl2e fldl2t fldlg2 fldln2 fldpi fldz fmul fmulp fnclex fndisi fneni fninit fnop fnsave fnstcw fnstenv fnstsw fpatan fprem fprem1 fptan frndint frstor fsave fscale fsetpm fsin fsincos fsqrt fst fstcw fstenv fstp fstsw fsub fsubp fsubr fsubrp ftst fucom fucomi fucomip fucomp fucompp fxam fxch fxtract fyl2x fyl2xp1 hlt ibts icebp idiv imul in inc incbin insb insd insw int int01 int1 int03 int3 into invd invpcid invlpg invlpga iret iretd iretq iretw jcxz jecxz jrcxz jmp jmpe lahf lar lds lea leave les lfence lfs lgdt lgs lidt lldt lmsw loadall loadall286 lodsb lodsd lodsq lodsw loop loope loopne loopnz loopz lsl lss ltr mfence monitor mov movd movq movsb movsd movsq movsw movsx movsxd movzx mul mwait neg nop not or out outsb outsd outsw packssdw packsswb packuswb paddb paddd paddsb paddsiw paddsw paddusb paddusw paddw pand pandn pause paveb pavgusb pcmpeqb pcmpeqd pcmpeqw pcmpgtb pcmpgtd pcmpgtw pdistib pf2id pfacc pfadd pfcmpeq pfcmpge pfcmpgt pfmax pfmin pfmul pfrcp pfrcpit1 pfrcpit2 pfrsqit1 pfrsqrt pfsub pfsubr pi2fd pmachriw pmaddwd pmagw pmulhriw pmulhrwa pmulhrwc pmulhw pmullw pmvgezb pmvlzb pmvnzb pmvzb pop popa popad popaw popf popfd popfq popfw por prefetch prefetchw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb psubd psubsb psubsiw psubsw psubusb psubusw psubw punpckhbw punpckhdq punpckhwd punpcklbw punpckldq punpcklwd push pusha pushad pushaw pushf pushfd pushfq pushfw pxor rcl rcr rdshr rdmsr rdpmc rdtsc rdtscp ret retf retn rol ror rdm rsdc rsldt rsm rsts sahf sal salc sar sbb scasb scasd scasq scasw sfence sgdt shl shld shr shrd sidt sldt skinit smi smint smintold smsw stc std sti stosb stosd stosq stosw str sub svdc svldt svts swapgs syscall sysenter sysexit sysret test ud0 ud1 ud2b ud2 ud2a umov verr verw fwait wbinvd wrshr wrmsr xadd xbts xchg xlatb xlat xor cmove cmovz cmovne cmovnz cmova cmovnbe cmovae cmovnb cmovb cmovnae cmovbe cmovna cmovg cmovnle cmovge cmovnl cmovl cmovnge cmovle cmovng cmovc cmovnc cmovo cmovno cmovs cmovns cmovp cmovpe cmovnp cmovpo je jz jne jnz ja jnbe jae jnb jb jnae jbe jna jg jnle jge jnl jl jnge jle jng jc jnc jo jno js jns jpo jnp jpe jp sete setz setne setnz seta setnbe setae setnb setnc setb setnae setcset setbe setna setg setnle setge setnl setl setnge setle setng sets setns seto setno setpe setp setpo setnp addps addss andnps andps cmpeqps cmpeqss cmpleps cmpless cmpltps cmpltss cmpneqps cmpneqss cmpnleps cmpnless cmpnltps cmpnltss cmpordps cmpordss cmpunordps cmpunordss cmpps cmpss comiss cvtpi2ps cvtps2pi cvtsi2ss cvtss2si cvttps2pi cvttss2si divps divss ldmxcsr maxps maxss minps minss movaps movhps movlhps movlps movhlps movmskps movntps movss movups mulps mulss orps rcpps rcpss rsqrtps rsqrtss shufps sqrtps sqrtss stmxcsr subps subss ucomiss unpckhps unpcklps xorps fxrstor fxrstor64 fxsave fxsave64 xgetbv xsetbv xsave xsave64 xsaveopt xsaveopt64 xrstor xrstor64 prefetchnta prefetcht0 prefetcht1 prefetcht2 maskmovq movntq pavgb pavgw pextrw pinsrw pmaxsw pmaxub pminsw pminub pmovmskb pmulhuw psadbw pshufw pf2iw pfnacc pfpnacc pi2fw pswapd maskmovdqu clflush movntdq movnti movntpd movdqa movdqu movdq2q movq2dq paddq pmuludq pshufd pshufhw pshuflw pslldq psrldq psubq punpckhqdq punpcklqdq addpd addsd andnpd andpd cmpeqpd cmpeqsd cmplepd cmplesd cmpltpd cmpltsd cmpneqpd cmpneqsd cmpnlepd cmpnlesd cmpnltpd cmpnltsd cmpordpd cmpordsd cmpunordpd cmpunordsd cmppd comisd cvtdq2pd cvtdq2ps cvtpd2dq cvtpd2pi cvtpd2ps cvtpi2pd cvtps2dq cvtps2pd cvtsd2si cvtsd2ss cvtsi2sd cvtss2sd cvttpd2pi cvttpd2dq cvttps2dq cvttsd2si divpd divsd maxpd maxsd minpd minsd movapd movhpd movlpd movmskpd movupd mulpd mulsd orpd shufpd sqrtpd sqrtsd subpd subsd ucomisd unpckhpd unpcklpd xorpd addsubpd addsubps haddpd haddps hsubpd hsubps lddqu movddup movshdup movsldup clgi stgi vmcall vmclear vmfunc vmlaunch vmload vmmcall vmptrld vmptrst vmread vmresume vmrun vmsave vmwrite vmxoff vmxon invept invvpid pabsb pabsw pabsd palignr phaddw phaddd phaddsw phsubw phsubd phsubsw pmaddubsw pmulhrsw pshufb psignb psignw psignd extrq insertq movntsd movntss lzcnt blendpd blendps blendvpd blendvps dppd dpps extractps insertps movntdqa mpsadbw packusdw pblendvb pblendw pcmpeqq pextrb pextrd pextrq phminposuw pinsrb pinsrd pinsrq pmaxsb pmaxsd pmaxud pmaxuw pminsb pminsd pminud pminuw pmovsxbw pmovsxbd pmovsxbq pmovsxwd pmovsxwq pmovsxdq pmovzxbw pmovzxbd pmovzxbq pmovzxwd pmovzxwq pmovzxdq pmuldq pmulld ptest roundpd roundps roundsd roundss crc32 pcmpestri pcmpestrm pcmpistri pcmpistrm pcmpgtq popcnt getsec pfrcpv pfrsqrtv movbe aesenc aesenclast aesdec aesdeclast aesimc aeskeygenassist vaesenc vaesenclast vaesdec vaesdeclast vaesimc vaeskeygenassist vaddpd vaddps vaddsd vaddss vaddsubpd vaddsubps vandpd vandps vandnpd vandnps vblendpd vblendps vblendvpd vblendvps vbroadcastss vbroadcastsd vbroadcastf128 vcmpeq_ospd vcmpeqpd vcmplt_ospd vcmpltpd vcmple_ospd vcmplepd vcmpunord_qpd vcmpunordpd vcmpneq_uqpd vcmpneqpd vcmpnlt_uspd vcmpnltpd vcmpnle_uspd vcmpnlepd vcmpord_qpd vcmpordpd vcmpeq_uqpd vcmpnge_uspd vcmpngepd vcmpngt_uspd vcmpngtpd vcmpfalse_oqpd vcmpfalsepd vcmpneq_oqpd vcmpge_ospd vcmpgepd vcmpgt_ospd vcmpgtpd vcmptrue_uqpd vcmptruepd vcmplt_oqpd vcmple_oqpd vcmpunord_spd vcmpneq_uspd vcmpnlt_uqpd vcmpnle_uqpd vcmpord_spd vcmpeq_uspd vcmpnge_uqpd vcmpngt_uqpd vcmpfalse_ospd vcmpneq_ospd vcmpge_oqpd vcmpgt_oqpd vcmptrue_uspd vcmppd vcmpeq_osps vcmpeqps vcmplt_osps vcmpltps vcmple_osps vcmpleps vcmpunord_qps vcmpunordps vcmpneq_uqps vcmpneqps vcmpnlt_usps vcmpnltps vcmpnle_usps vcmpnleps vcmpord_qps vcmpordps vcmpeq_uqps vcmpnge_usps vcmpngeps vcmpngt_usps vcmpngtps vcmpfalse_oqps vcmpfalseps vcmpneq_oqps vcmpge_osps vcmpgeps vcmpgt_osps vcmpgtps vcmptrue_uqps vcmptrueps vcmplt_oqps vcmple_oqps vcmpunord_sps vcmpneq_usps vcmpnlt_uqps vcmpnle_uqps vcmpord_sps vcmpeq_usps vcmpnge_uqps vcmpngt_uqps vcmpfalse_osps vcmpneq_osps vcmpge_oqps vcmpgt_oqps vcmptrue_usps vcmpps vcmpeq_ossd vcmpeqsd vcmplt_ossd vcmpltsd vcmple_ossd vcmplesd vcmpunord_qsd vcmpunordsd vcmpneq_uqsd vcmpneqsd vcmpnlt_ussd vcmpnltsd vcmpnle_ussd vcmpnlesd vcmpord_qsd vcmpordsd vcmpeq_uqsd vcmpnge_ussd vcmpngesd vcmpngt_ussd vcmpngtsd vcmpfalse_oqsd vcmpfalsesd vcmpneq_oqsd vcmpge_ossd vcmpgesd vcmpgt_ossd vcmpgtsd vcmptrue_uqsd vcmptruesd vcmplt_oqsd vcmple_oqsd vcmpunord_ssd vcmpneq_ussd vcmpnlt_uqsd vcmpnle_uqsd vcmpord_ssd vcmpeq_ussd vcmpnge_uqsd vcmpngt_uqsd vcmpfalse_ossd vcmpneq_ossd vcmpge_oqsd vcmpgt_oqsd vcmptrue_ussd vcmpsd vcmpeq_osss vcmpeqss vcmplt_osss vcmpltss vcmple_osss vcmpless vcmpunord_qss vcmpunordss vcmpneq_uqss vcmpneqss vcmpnlt_usss vcmpnltss vcmpnle_usss vcmpnless vcmpord_qss vcmpordss vcmpeq_uqss vcmpnge_usss vcmpngess vcmpngt_usss vcmpngtss vcmpfalse_oqss vcmpfalsess vcmpneq_oqss vcmpge_osss vcmpgess vcmpgt_osss vcmpgtss vcmptrue_uqss vcmptruess vcmplt_oqss vcmple_oqss vcmpunord_sss vcmpneq_usss vcmpnlt_uqss vcmpnle_uqss vcmpord_sss vcmpeq_usss vcmpnge_uqss vcmpngt_uqss vcmpfalse_osss vcmpneq_osss vcmpge_oqss vcmpgt_oqss vcmptrue_usss vcmpss vcomisd vcomiss vcvtdq2pd vcvtdq2ps vcvtpd2dq vcvtpd2ps vcvtps2dq vcvtps2pd vcvtsd2si vcvtsd2ss vcvtsi2sd vcvtsi2ss vcvtss2sd vcvtss2si vcvttpd2dq vcvttps2dq vcvttsd2si vcvttss2si vdivpd vdivps vdivsd vdivss vdppd vdpps vextractf128 vextractps vhaddpd vhaddps vhsubpd vhsubps vinsertf128 vinsertps vlddqu vldqqu vldmxcsr vmaskmovdqu vmaskmovps vmaskmovpd vmaxpd vmaxps vmaxsd vmaxss vminpd vminps vminsd vminss vmovapd vmovaps vmovd vmovq vmovddup vmovdqa vmovqqa vmovdqu vmovqqu vmovhlps vmovhpd vmovhps vmovlhps vmovlpd vmovlps vmovmskpd vmovmskps vmovntdq vmovntqq vmovntdqa vmovntpd vmovntps vmovsd vmovshdup vmovsldup vmovss vmovupd vmovups vmpsadbw vmulpd vmulps vmulsd vmulss vorpd vorps vpabsb vpabsw vpabsd vpacksswb vpackssdw vpackuswb vpackusdw vpaddb vpaddw vpaddd vpaddq vpaddsb vpaddsw vpaddusb vpaddusw vpalignr vpand vpandn vpavgb vpavgw vpblendvb vpblendw vpcmpestri vpcmpestrm vpcmpistri vpcmpistrm vpcmpeqb vpcmpeqw vpcmpeqd vpcmpeqq vpcmpgtb vpcmpgtw vpcmpgtd vpcmpgtq vpermilpd vpermilps vperm2f128 vpextrb vpextrw vpextrd vpextrq vphaddw vphaddd vphaddsw vphminposuw vphsubw vphsubd vphsubsw vpinsrb vpinsrw vpinsrd vpinsrq vpmaddwd vpmaddubsw vpmaxsb vpmaxsw vpmaxsd vpmaxub vpmaxuw vpmaxud vpminsb vpminsw vpminsd vpminub vpminuw vpminud vpmovmskb vpmovsxbw vpmovsxbd vpmovsxbq vpmovsxwd vpmovsxwq vpmovsxdq vpmovzxbw vpmovzxbd vpmovzxbq vpmovzxwd vpmovzxwq vpmovzxdq vpmulhuw vpmulhrsw vpmulhw vpmullw vpmulld vpmuludq vpmuldq vpor vpsadbw vpshufb vpshufd vpshufhw vpshuflw vpsignb vpsignw vpsignd vpslldq vpsrldq vpsllw vpslld vpsllq vpsraw vpsrad vpsrlw vpsrld vpsrlq vptest vpsubb vpsubw vpsubd vpsubq vpsubsb vpsubsw vpsubusb vpsubusw vpunpckhbw vpunpckhwd vpunpckhdq vpunpckhqdq vpunpcklbw vpunpcklwd vpunpckldq vpunpcklqdq vpxor vrcpps vrcpss vrsqrtps vrsqrtss vroundpd vroundps vroundsd vroundss vshufpd vshufps vsqrtpd vsqrtps vsqrtsd vsqrtss vstmxcsr vsubpd vsubps vsubsd vsubss vtestps vtestpd vucomisd vucomiss vunpckhpd vunpckhps vunpcklpd vunpcklps vxorpd vxorps vzeroall vzeroupper pclmullqlqdq pclmulhqlqdq pclmullqhqdq pclmulhqhqdq pclmulqdq vpclmullqlqdq vpclmulhqlqdq vpclmullqhqdq vpclmulhqhqdq vpclmulqdq vfmadd132ps vfmadd132pd vfmadd312ps vfmadd312pd vfmadd213ps vfmadd213pd vfmadd123ps vfmadd123pd vfmadd231ps vfmadd231pd vfmadd321ps vfmadd321pd vfmaddsub132ps vfmaddsub132pd vfmaddsub312ps vfmaddsub312pd vfmaddsub213ps vfmaddsub213pd vfmaddsub123ps vfmaddsub123pd vfmaddsub231ps vfmaddsub231pd vfmaddsub321ps vfmaddsub321pd vfmsub132ps vfmsub132pd vfmsub312ps vfmsub312pd vfmsub213ps vfmsub213pd vfmsub123ps vfmsub123pd vfmsub231ps vfmsub231pd vfmsub321ps vfmsub321pd vfmsubadd132ps vfmsubadd132pd vfmsubadd312ps vfmsubadd312pd vfmsubadd213ps vfmsubadd213pd vfmsubadd123ps vfmsubadd123pd vfmsubadd231ps vfmsubadd231pd vfmsubadd321ps vfmsubadd321pd vfnmadd132ps vfnmadd132pd vfnmadd312ps vfnmadd312pd vfnmadd213ps vfnmadd213pd vfnmadd123ps vfnmadd123pd vfnmadd231ps vfnmadd231pd vfnmadd321ps vfnmadd321pd vfnmsub132ps vfnmsub132pd vfnmsub312ps vfnmsub312pd vfnmsub213ps vfnmsub213pd vfnmsub123ps vfnmsub123pd vfnmsub231ps vfnmsub231pd vfnmsub321ps vfnmsub321pd vfmadd132ss vfmadd132sd vfmadd312ss vfmadd312sd vfmadd213ss vfmadd213sd vfmadd123ss vfmadd123sd vfmadd231ss vfmadd231sd vfmadd321ss vfmadd321sd vfmsub132ss vfmsub132sd vfmsub312ss vfmsub312sd vfmsub213ss vfmsub213sd vfmsub123ss vfmsub123sd vfmsub231ss vfmsub231sd vfmsub321ss vfmsub321sd vfnmadd132ss vfnmadd132sd vfnmadd312ss vfnmadd312sd vfnmadd213ss vfnmadd213sd vfnmadd123ss vfnmadd123sd vfnmadd231ss vfnmadd231sd vfnmadd321ss vfnmadd321sd vfnmsub132ss vfnmsub132sd vfnmsub312ss vfnmsub312sd vfnmsub213ss vfnmsub213sd vfnmsub123ss vfnmsub123sd vfnmsub231ss vfnmsub231sd vfnmsub321ss vfnmsub321sd rdfsbase rdgsbase rdrand wrfsbase wrgsbase vcvtph2ps vcvtps2ph adcx adox rdseed clac stac xstore xcryptecb xcryptcbc xcryptctr xcryptcfb xcryptofb montmul xsha1 xsha256 llwpcb slwpcb lwpval lwpins vfmaddpd vfmaddps vfmaddsd vfmaddss vfmaddsubpd vfmaddsubps vfmsubaddpd vfmsubaddps vfmsubpd vfmsubps vfmsubsd vfmsubss vfnmaddpd vfnmaddps vfnmaddsd vfnmaddss vfnmsubpd vfnmsubps vfnmsubsd vfnmsubss vfrczpd vfrczps vfrczsd vfrczss vpcmov vpcomb vpcomd vpcomq vpcomub vpcomud vpcomuq vpcomuw vpcomw vphaddbd vphaddbq vphaddbw vphadddq vphaddubd vphaddubq vphaddubw vphaddudq vphadduwd vphadduwq vphaddwd vphaddwq vphsubbw vphsubdq vphsubwd vpmacsdd vpmacsdqh vpmacsdql vpmacssdd vpmacssdqh vpmacssdql vpmacsswd vpmacssww vpmacswd vpmacsww vpmadcsswd vpmadcswd vpperm vprotb vprotd vprotq vprotw vpshab vpshad vpshaq vpshaw vpshlb vpshld vpshlq vpshlw vbroadcasti128 vpblendd vpbroadcastb vpbroadcastw vpbroadcastd vpbroadcastq vpermd vpermpd vpermps vpermq vperm2i128 vextracti128 vinserti128 vpmaskmovd vpmaskmovq vpsllvd vpsllvq vpsravd vpsrlvd vpsrlvq vgatherdpd vgatherqpd vgatherdps vgatherqps vpgatherdd vpgatherqd vpgatherdq vpgatherqq xabort xbegin xend xtest andn bextr blci blcic blsi blsic blcfill blsfill blcmsk blsmsk blsr blcs bzhi mulx pdep pext rorx sarx shlx shrx tzcnt tzmsk t1mskc valignd valignq vblendmpd vblendmps vbroadcastf32x4 vbroadcastf64x4 vbroadcasti32x4 vbroadcasti64x4 vcompresspd vcompressps vcvtpd2udq vcvtps2udq vcvtsd2usi vcvtss2usi vcvttpd2udq vcvttps2udq vcvttsd2usi vcvttss2usi vcvtudq2pd vcvtudq2ps vcvtusi2sd vcvtusi2ss vexpandpd vexpandps vextractf32x4 vextractf64x4 vextracti32x4 vextracti64x4 vfixupimmpd vfixupimmps vfixupimmsd vfixupimmss vgetexppd vgetexpps vgetexpsd vgetexpss vgetmantpd vgetmantps vgetmantsd vgetmantss vinsertf32x4 vinsertf64x4 vinserti32x4 vinserti64x4 vmovdqa32 vmovdqa64 vmovdqu32 vmovdqu64 vpabsq vpandd vpandnd vpandnq vpandq vpblendmd vpblendmq vpcmpltd vpcmpled vpcmpneqd vpcmpnltd vpcmpnled vpcmpd vpcmpltq vpcmpleq vpcmpneqq vpcmpnltq vpcmpnleq vpcmpq vpcmpequd vpcmpltud vpcmpleud vpcmpnequd vpcmpnltud vpcmpnleud vpcmpud vpcmpequq vpcmpltuq vpcmpleuq vpcmpnequq vpcmpnltuq vpcmpnleuq vpcmpuq vpcompressd vpcompressq vpermi2d vpermi2pd vpermi2ps vpermi2q vpermt2d vpermt2pd vpermt2ps vpermt2q vpexpandd vpexpandq vpmaxsq vpmaxuq vpminsq vpminuq vpmovdb vpmovdw vpmovqb vpmovqd vpmovqw vpmovsdb vpmovsdw vpmovsqb vpmovsqd vpmovsqw vpmovusdb vpmovusdw vpmovusqb vpmovusqd vpmovusqw vpord vporq vprold vprolq vprolvd vprolvq vprord vprorq vprorvd vprorvq vpscatterdd vpscatterdq vpscatterqd vpscatterqq vpsraq vpsravq vpternlogd vpternlogq vptestmd vptestmq vptestnmd vptestnmq vpxord vpxorq vrcp14pd vrcp14ps vrcp14sd vrcp14ss vrndscalepd vrndscaleps vrndscalesd vrndscaless vrsqrt14pd vrsqrt14ps vrsqrt14sd vrsqrt14ss vscalefpd vscalefps vscalefsd vscalefss vscatterdpd vscatterdps vscatterqpd vscatterqps vshuff32x4 vshuff64x2 vshufi32x4 vshufi64x2 kandnw kandw kmovw knotw kortestw korw kshiftlw kshiftrw kunpckbw kxnorw kxorw vpbroadcastmb2q vpbroadcastmw2d vpconflictd vpconflictq vplzcntd vplzcntq vexp2pd vexp2ps vrcp28pd vrcp28ps vrcp28sd vrcp28ss vrsqrt28pd vrsqrt28ps vrsqrt28sd vrsqrt28ss vgatherpf0dpd vgatherpf0dps vgatherpf0qpd vgatherpf0qps vgatherpf1dpd vgatherpf1dps vgatherpf1qpd vgatherpf1qps vscatterpf0dpd vscatterpf0dps vscatterpf0qpd vscatterpf0qps vscatterpf1dpd vscatterpf1dps vscatterpf1qpd vscatterpf1qps prefetchwt1 bndmk bndcl bndcu bndcn bndmov bndldx bndstx sha1rnds4 sha1nexte sha1msg1 sha1msg2 sha256rnds2 sha256msg1 sha256msg2 hint_nop0 hint_nop1 hint_nop2 hint_nop3 hint_nop4 hint_nop5 hint_nop6 hint_nop7 hint_nop8 hint_nop9 hint_nop10 hint_nop11 hint_nop12 hint_nop13 hint_nop14 hint_nop15 hint_nop16 hint_nop17 hint_nop18 hint_nop19 hint_nop20 hint_nop21 hint_nop22 hint_nop23 hint_nop24 hint_nop25 hint_nop26 hint_nop27 hint_nop28 hint_nop29 hint_nop30 hint_nop31 hint_nop32 hint_nop33 hint_nop34 hint_nop35 hint_nop36 hint_nop37 hint_nop38 hint_nop39 hint_nop40 hint_nop41 hint_nop42 hint_nop43 hint_nop44 hint_nop45 hint_nop46 hint_nop47 hint_nop48 hint_nop49 hint_nop50 hint_nop51 hint_nop52 hint_nop53 hint_nop54 hint_nop55 hint_nop56 hint_nop57 hint_nop58 hint_nop59 hint_nop60 hint_nop61 hint_nop62 hint_nop63",built_in:"ip eip rip al ah bl bh cl ch dl dh sil dil bpl spl r8b r9b r10b r11b r12b r13b r14b r15b ax bx cx dx si di bp sp r8w r9w r10w r11w r12w r13w r14w r15w eax ebx ecx edx esi edi ebp esp eip r8d r9d r10d r11d r12d r13d r14d r15d rax rbx rcx rdx rsi rdi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15 cs ds es fs gs ss st st0 st1 st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7 xmm8 xmm9 xmm10 xmm11 xmm12 xmm13 xmm14 xmm15 xmm16 xmm17 xmm18 xmm19 xmm20 xmm21 xmm22 xmm23 xmm24 xmm25 xmm26 xmm27 xmm28 xmm29 xmm30 xmm31 ymm0 ymm1 ymm2 ymm3 ymm4 ymm5 ymm6 ymm7 ymm8 ymm9 ymm10 ymm11 ymm12 ymm13 ymm14 ymm15 ymm16 ymm17 ymm18 ymm19 ymm20 ymm21 ymm22 ymm23 ymm24 ymm25 ymm26 ymm27 ymm28 ymm29 ymm30 ymm31 zmm0 zmm1 zmm2 zmm3 zmm4 zmm5 zmm6 zmm7 zmm8 zmm9 zmm10 zmm11 zmm12 zmm13 zmm14 zmm15 zmm16 zmm17 zmm18 zmm19 zmm20 zmm21 zmm22 zmm23 zmm24 zmm25 zmm26 zmm27 zmm28 zmm29 zmm30 zmm31 k0 k1 k2 k3 k4 k5 k6 k7 bnd0 bnd1 bnd2 bnd3 cr0 cr1 cr2 cr3 cr4 cr8 dr0 dr1 dr2 dr3 dr8 tr3 tr4 tr5 tr6 tr7 r0 r1 r2 r3 r4 r5 r6 r7 r0b r1b r2b r3b r4b r5b r6b r7b r0w r1w r2w r3w r4w r5w r6w r7w r0d r1d r2d r3d r4d r5d r6d r7d r0h r1h r2h r3h r0l r1l r2l r3l r4l r5l r6l r7l r8l r9l r10l r11l r12l r13l r14l r15l db dw dd dq dt ddq do dy dz resb resw resd resq rest resdq reso resy resz incbin equ times byte word dword qword nosplit rel abs seg wrt strict near far a32 ptr",meta:"%define %xdefine %+ %undef %defstr %deftok %assign %strcat %strlen %substr %rotate %elif %else %endif %if %ifmacro %ifctx %ifidn %ifidni %ifid %ifnum %ifstr %iftoken %ifempty %ifenv %error %warning %fatal %rep %endrep %include %push %pop %repl %pathsearch %depend %use %arg %stacksize %local %line %comment %endcomment .nolist __FILE__ __LINE__ __SECT__ __BITS__ __OUTPUT_FORMAT__ __DATE__ __TIME__ __DATE_NUM__ __TIME_NUM__ __UTC_DATE__ __UTC_TIME__ __UTC_DATE_NUM__ __UTC_TIME_NUM__ __PASS__ struc endstruc istruc at iend align alignb sectalign daz nodaz up down zero default option assume public bits use16 use32 use64 default section segment absolute extern global common cpu float __utf16__ __utf16le__ __utf16be__ __utf32__ __utf32le__ __utf32be__ __float8__ __float16__ __float32__ __float64__ __float80m__ __float80e__ __float128l__ __float128h__ __Infinity__ __QNaN__ __SNaN__ Inf NaN QNaN SNaN float8 float16 float32 float64 float80m float80e float128l float128h __FLOAT_DAZ__ __FLOAT_ROUND__ __FLOAT__"},contains:[s.COMMENT(";","$",{relevance:0}),{className:"number",variants:[{begin:"\\b(?:([0-9][0-9_]*)?\\.[0-9_]*(?:[eE][+-]?[0-9_]+)?|(0[Xx])?[0-9][0-9_]*\\.?[0-9_]*(?:[pP](?:[+-]?[0-9_]+)?)?)\\b",relevance:0},{begin:"\\$[0-9][0-9A-Fa-f]*",relevance:0},{begin:"\\b(?:[0-9A-Fa-f][0-9A-Fa-f_]*[Hh]|[0-9][0-9_]*[DdTt]?|[0-7][0-7_]*[QqOo]|[0-1][0-1_]*[BbYy])\\b"},{begin:"\\b(?:0[Xx][0-9A-Fa-f_]+|0[DdTt][0-9_]+|0[QqOo][0-7_]+|0[BbYy][0-1_]+)\\b"}]},s.QUOTE_STRING_MODE,{className:"string",variants:[{begin:"'",end:"[^\\\\]'"},{begin:"`",end:"[^\\\\]`"}],relevance:0},{className:"symbol",variants:[{begin:"^\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\s+label)"},{begin:"^\\s*%%[A-Za-z0-9_$#@~.?]*:"}],relevance:0},{className:"subst",begin:"%[0-9]+",relevance:0},{className:"subst",begin:"%!S+",relevance:0},{className:"meta",begin:/^\s*\.[\w_-]+/}]}}}()); \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..0e44879 --- /dev/null +++ b/index.html @@ -0,0 +1,279 @@ + + + + + + Introduction - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

vidformer - Video Data Transformation

+

Test +PyPI version +Crates.io Version +Open In Colab +License

+

A research project providing infrastructure for video interfaces and pipelines. +Developed by the OSU Interactive Data Systems Lab.

+

🎯 Why vidformer

+

Vidformer efficiently transforms video data, enabling faster annotation, editing, and processing of video data—without having to focus on performance.

+

It uses a declarative specification format to represent transformations. This enables:

+
    +
  • +

    ⚡ Transparent Optimization: Vidformer optimizes the execution of declarative specifications just like a relational database optimizes relational queries.

    +
  • +
  • +

    ⏳ Lazy/Deferred Execution: Video results can be retrieved on-demand, allowing for practically instantaneous playback of video results.

    +
  • +
  • +

    🔄 Transpilation: Vidformer specifications can be created from existing code (like cv2).

    +
  • +
+

🚀 Quick Start

+

Open In Colab

+

The easiest way to get started is using vidformer's cv2 frontend, which allows most Python OpenCV visualization scripts to replace import cv2 with import vidformer.cv2 as cv2:

+
import vidformer.cv2 as cv2
+
+cap = cv2.VideoCapture("my_input.mp4")
+fps = cap.get(cv2.CAP_PROP_FPS)
+width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+out = cv2.VideoWriter("my_output.mp4", cv2.VideoWriter_fourcc(*"mp4v"),
+                        fps, (width, height))
+while True:
+    ret, frame = cap.read()
+    if not ret:
+      break
+
+    cv2.putText(frame, "Hello, World!", (100, 100), cv2.FONT_HERSHEY_SIMPLEX,
+                1, (255, 0, 0), 1)
+    out.write(frame)
+
+cap.release()
+out.release()
+
+

You can find details on this in our Getting Started Guide.

+

📘 Documentation

+ +

🔍 About the project

+

Vidformer is a highly modular suite of tools that work together; these are detailed here.

+

❌ vidformer is NOT:

+
    +
  • A conventional video editor (like Premiere Pro or Final Cut)
  • +
  • A video database/VDBMS
  • +
  • A natural language query interface for video
  • +
  • A computer vision library (like OpenCV)
  • +
  • A computer vision AI model (like CLIP or Yolo)
  • +
+

However, vidformer is highly complementary to each of these. +If you're working on any of the later four, vidformer may be for you.

+

File Layout:

+ +

License: Vidformer is open source under Apache-2.0. +Contributions welcome.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/install.html b/install.html new file mode 100644 index 0000000..878ee6f --- /dev/null +++ b/install.html @@ -0,0 +1,251 @@ + + + + + + Install - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

Install

+

Using vidformer requires the Python client library, vidformer-py, and a yrden server which is distributed through vidformer-cli.

+

vidformer-py

+
pip install vidformer
+
+

vidformer-cli

+

🐳 Docker:

+
docker pull dominikwinecki/vidformer:latest
+docker run --rm -it -p 8000:8000 dominikwinecki/vidformer:latest yrden --print-url
+
+

This launches a vidformer yrden server, which is our reference server implementation for local usage, on port 8000. +If you want to read or save video files locally add -v /my/local/dir:/data and then reference them as /data in the code.

+

To use:

+
import vidformer as vf
+server = vf.YrdenServer(domain="localhost", port=8000)
+
+# or for cv2
+import vidformer.cv2 as cv2
+cv2.set_cv2_server(server)
+
+

Precompiled binary:

+

Precompiled binaries are available for vidformer releases.

+

For example:

+
wget https://github.com/ixlab/vidformer/releases/download/<version>/vidformer-cli-ubuntu22.04-amd64
+sudo mv  vidformer-cli-ubuntu22.04-amd64 /usr/local/bin/vidformer-cli
+sudo chmod +x /usr/local/bin/vidformer-cli
+sudo apt install -y libopencv-dev libfdk-aac-dev
+
+

To use:

+
import vidformer as vf
+server = vf.YrdenServer(bin="vidformer-cli")
+
+

or

+
export VIDFORMER_BIN='vidformer-cli'
+
+
import vidformer as vf
+server = vf.YrdenServer()
+
+

Build from Sources

+

vidformer-cli can be compiled from our git repo with a standard cargo build.

+

This depends on the core vidformer library which itself requires linking to FFmpeg and OpenCV. +Details are available here.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/introduction.html b/introduction.html new file mode 100644 index 0000000..0e44879 --- /dev/null +++ b/introduction.html @@ -0,0 +1,279 @@ + + + + + + Introduction - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

vidformer - Video Data Transformation

+

Test +PyPI version +Crates.io Version +Open In Colab +License

+

A research project providing infrastructure for video interfaces and pipelines. +Developed by the OSU Interactive Data Systems Lab.

+

🎯 Why vidformer

+

Vidformer efficiently transforms video data, enabling faster annotation, editing, and processing of video data—without having to focus on performance.

+

It uses a declarative specification format to represent transformations. This enables:

+
    +
  • +

    ⚡ Transparent Optimization: Vidformer optimizes the execution of declarative specifications just like a relational database optimizes relational queries.

    +
  • +
  • +

    ⏳ Lazy/Deferred Execution: Video results can be retrieved on-demand, allowing for practically instantaneous playback of video results.

    +
  • +
  • +

    🔄 Transpilation: Vidformer specifications can be created from existing code (like cv2).

    +
  • +
+

🚀 Quick Start

+

Open In Colab

+

The easiest way to get started is using vidformer's cv2 frontend, which allows most Python OpenCV visualization scripts to replace import cv2 with import vidformer.cv2 as cv2:

+
import vidformer.cv2 as cv2
+
+cap = cv2.VideoCapture("my_input.mp4")
+fps = cap.get(cv2.CAP_PROP_FPS)
+width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+out = cv2.VideoWriter("my_output.mp4", cv2.VideoWriter_fourcc(*"mp4v"),
+                        fps, (width, height))
+while True:
+    ret, frame = cap.read()
+    if not ret:
+      break
+
+    cv2.putText(frame, "Hello, World!", (100, 100), cv2.FONT_HERSHEY_SIMPLEX,
+                1, (255, 0, 0), 1)
+    out.write(frame)
+
+cap.release()
+out.release()
+
+

You can find details on this in our Getting Started Guide.

+

📘 Documentation

+ +

🔍 About the project

+

Vidformer is a highly modular suite of tools that work together; these are detailed here.

+

❌ vidformer is NOT:

+
    +
  • A conventional video editor (like Premiere Pro or Final Cut)
  • +
  • A video database/VDBMS
  • +
  • A natural language query interface for video
  • +
  • A computer vision library (like OpenCV)
  • +
  • A computer vision AI model (like CLIP or Yolo)
  • +
+

However, vidformer is highly complementary to each of these. +If you're working on any of the later four, vidformer may be for you.

+

File Layout:

+ +

License: Vidformer is open source under Apache-2.0. +Contributions welcome.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/libvidformer.html b/libvidformer.html new file mode 100644 index 0000000..435eea4 --- /dev/null +++ b/libvidformer.html @@ -0,0 +1,242 @@ + + + + + + libvidformer - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

vidformer - Video Data Transformation Library

+

Crates.io Version +License

+

(lib)vidformer is a core video synthesis/transformation library. +It handles the movement, control flow, and processing of video and conventional (non-video) data.

+

Quick links:

+ +

About

+
    +
  • It's written in Rust 🦀 +
      +
    • So it does some fancy parallel processing and does so safely
    • +
    +
  • +
  • Uses the FFmpeg libav libraries for multimedia stuff +
      +
    • So it should work with nearly every video file ever made
    • +
    +
  • +
  • Uses Apache OpenDAL for I/O +
      +
    • So it can access videos in a bunch of storage services
    • +
    +
  • +
  • Implements filters using OpenCV
  • +
+

Building

+

This crate requires linking with FFmpeg, as detailed in the rusty_ffmpeg crate. +We currently target FFmpeg 7.0.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/mark.min.js b/mark.min.js new file mode 100644 index 0000000..1636231 --- /dev/null +++ b/mark.min.js @@ -0,0 +1,7 @@ +/*!*************************************************** +* mark.js v8.11.1 +* https://markjs.io/ +* Copyright (c) 2014–2018, Julian Kühnel +* Released under the MIT license https://git.io/vwTVl +*****************************************************/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Mark=t()}(this,function(){"use strict";var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},n=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:5e3;t(this,e),this.ctx=n,this.iframes=r,this.exclude=i,this.iframesTimeout=o}return n(e,[{key:"getContexts",value:function(){var e=[];return(void 0!==this.ctx&&this.ctx?NodeList.prototype.isPrototypeOf(this.ctx)?Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?this.ctx:"string"==typeof this.ctx?Array.prototype.slice.call(document.querySelectorAll(this.ctx)):[this.ctx]:[]).forEach(function(t){var n=e.filter(function(e){return e.contains(t)}).length>0;-1!==e.indexOf(t)||n||e.push(t)}),e}},{key:"getIframeContents",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},r=void 0;try{var i=e.contentWindow;if(r=i.document,!i||!r)throw new Error("iframe inaccessible")}catch(e){n()}r&&t(r)}},{key:"isIframeBlank",value:function(e){var t="about:blank",n=e.getAttribute("src").trim();return e.contentWindow.location.href===t&&n!==t&&n}},{key:"observeIframeLoad",value:function(e,t,n){var r=this,i=!1,o=null,a=function a(){if(!i){i=!0,clearTimeout(o);try{r.isIframeBlank(e)||(e.removeEventListener("load",a),r.getIframeContents(e,t,n))}catch(e){n()}}};e.addEventListener("load",a),o=setTimeout(a,this.iframesTimeout)}},{key:"onIframeReady",value:function(e,t,n){try{"complete"===e.contentWindow.document.readyState?this.isIframeBlank(e)?this.observeIframeLoad(e,t,n):this.getIframeContents(e,t,n):this.observeIframeLoad(e,t,n)}catch(e){n()}}},{key:"waitForIframes",value:function(e,t){var n=this,r=0;this.forEachIframe(e,function(){return!0},function(e){r++,n.waitForIframes(e.querySelector("html"),function(){--r||t()})},function(e){e||t()})}},{key:"forEachIframe",value:function(t,n,r){var i=this,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},a=t.querySelectorAll("iframe"),s=a.length,c=0;a=Array.prototype.slice.call(a);var u=function(){--s<=0&&o(c)};s||u(),a.forEach(function(t){e.matches(t,i.exclude)?u():i.onIframeReady(t,function(e){n(t)&&(c++,r(e)),u()},u)})}},{key:"createIterator",value:function(e,t,n){return document.createNodeIterator(e,t,n,!1)}},{key:"createInstanceOnIframe",value:function(t){return new e(t.querySelector("html"),this.iframes)}},{key:"compareNodeIframe",value:function(e,t,n){if(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_PRECEDING){if(null===t)return!0;if(t.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)return!0}return!1}},{key:"getIteratorNode",value:function(e){var t=e.previousNode();return{prevNode:t,node:null===t?e.nextNode():e.nextNode()&&e.nextNode()}}},{key:"checkIframeFilter",value:function(e,t,n,r){var i=!1,o=!1;return r.forEach(function(e,t){e.val===n&&(i=t,o=e.handled)}),this.compareNodeIframe(e,t,n)?(!1!==i||o?!1===i||o||(r[i].handled=!0):r.push({val:n,handled:!0}),!0):(!1===i&&r.push({val:n,handled:!1}),!1)}},{key:"handleOpenIframes",value:function(e,t,n,r){var i=this;e.forEach(function(e){e.handled||i.getIframeContents(e.val,function(e){i.createInstanceOnIframe(e).forEachNode(t,n,r)})})}},{key:"iterateThroughNodes",value:function(e,t,n,r,i){for(var o,a=this,s=this.createIterator(t,e,r),c=[],u=[],l=void 0,h=void 0;void 0,o=a.getIteratorNode(s),h=o.prevNode,l=o.node;)this.iframes&&this.forEachIframe(t,function(e){return a.checkIframeFilter(l,h,e,c)},function(t){a.createInstanceOnIframe(t).forEachNode(e,function(e){return u.push(e)},r)}),u.push(l);u.forEach(function(e){n(e)}),this.iframes&&this.handleOpenIframes(c,e,n,r),i()}},{key:"forEachNode",value:function(e,t,n){var r=this,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},o=this.getContexts(),a=o.length;a||i(),o.forEach(function(o){var s=function(){r.iterateThroughNodes(e,o,t,n,function(){--a<=0&&i()})};r.iframes?r.waitForIframes(o,s):s()})}}],[{key:"matches",value:function(e,t){var n="string"==typeof t?[t]:t,r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(r){var i=!1;return n.every(function(t){return!r.call(e,t)||(i=!0,!1)}),i}return!1}}]),e}(),o=function(){function e(n){t(this,e),this.opt=r({},{diacritics:!0,synonyms:{},accuracy:"partially",caseSensitive:!1,ignoreJoiners:!1,ignorePunctuation:[],wildcards:"disabled"},n)}return n(e,[{key:"create",value:function(e){return"disabled"!==this.opt.wildcards&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),"disabled"!==this.opt.wildcards&&(e=this.createWildcardsRegExp(e)),e=this.createAccuracyRegExp(e),new RegExp(e,"gm"+(this.opt.caseSensitive?"":"i"))}},{key:"escapeStr",value:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}},{key:"createSynonymsRegExp",value:function(e){var t=this.opt.synonyms,n=this.opt.caseSensitive?"":"i",r=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(var i in t)if(t.hasOwnProperty(i)){var o=t[i],a="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(i):this.escapeStr(i),s="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(o):this.escapeStr(o);""!==a&&""!==s&&(e=e.replace(new RegExp("("+this.escapeStr(a)+"|"+this.escapeStr(s)+")","gm"+n),r+"("+this.processSynonyms(a)+"|"+this.processSynonyms(s)+")"+r))}return e}},{key:"processSynonyms",value:function(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}},{key:"setupWildcardsRegExp",value:function(e){return(e=e.replace(/(?:\\)*\?/g,function(e){return"\\"===e.charAt(0)?"?":""})).replace(/(?:\\)*\*/g,function(e){return"\\"===e.charAt(0)?"*":""})}},{key:"createWildcardsRegExp",value:function(e){var t="withSpaces"===this.opt.wildcards;return e.replace(/\u0001/g,t?"[\\S\\s]?":"\\S?").replace(/\u0002/g,t?"[\\S\\s]*?":"\\S*")}},{key:"setupIgnoreJoinersRegExp",value:function(e){return e.replace(/[^(|)\\]/g,function(e,t,n){var r=n.charAt(t+1);return/[(|)\\]/.test(r)||""===r?e:e+"\0"})}},{key:"createJoinersRegExp",value:function(e){var t=[],n=this.opt.ignorePunctuation;return Array.isArray(n)&&n.length&&t.push(this.escapeStr(n.join(""))),this.opt.ignoreJoiners&&t.push("\\u00ad\\u200b\\u200c\\u200d"),t.length?e.split(/\u0000+/).join("["+t.join("")+"]*"):e}},{key:"createDiacriticsRegExp",value:function(e){var t=this.opt.caseSensitive?"":"i",n=this.opt.caseSensitive?["aàáảãạăằắẳẵặâầấẩẫậäåāą","AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćč","CÇĆČ","dđď","DĐĎ","eèéẻẽẹêềếểễệëěēę","EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïī","IÌÍỈĨỊÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøō","OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúủũụưừứửữựûüůū","UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿ","YÝỲỶỸỴŸ","zžżź","ZŽŻŹ"]:["aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćčCÇĆČ","dđďDĐĎ","eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïīIÌÍỈĨỊÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿYÝỲỶỸỴŸ","zžżźZŽŻŹ"],r=[];return e.split("").forEach(function(i){n.every(function(n){if(-1!==n.indexOf(i)){if(r.indexOf(n)>-1)return!1;e=e.replace(new RegExp("["+n+"]","gm"+t),"["+n+"]"),r.push(n)}return!0})}),e}},{key:"createMergedBlanksRegExp",value:function(e){return e.replace(/[\s]+/gim,"[\\s]+")}},{key:"createAccuracyRegExp",value:function(e){var t=this,n=this.opt.accuracy,r="string"==typeof n?n:n.value,i="";switch(("string"==typeof n?[]:n.limiters).forEach(function(e){i+="|"+t.escapeStr(e)}),r){case"partially":default:return"()("+e+")";case"complementary":return"()([^"+(i="\\s"+(i||this.escapeStr("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿")))+"]*"+e+"[^"+i+"]*)";case"exactly":return"(^|\\s"+i+")("+e+")(?=$|\\s"+i+")"}}}]),e}(),a=function(){function a(e){t(this,a),this.ctx=e,this.ie=!1;var n=window.navigator.userAgent;(n.indexOf("MSIE")>-1||n.indexOf("Trident")>-1)&&(this.ie=!0)}return n(a,[{key:"log",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"debug",r=this.opt.log;this.opt.debug&&"object"===(void 0===r?"undefined":e(r))&&"function"==typeof r[n]&&r[n]("mark.js: "+t)}},{key:"getSeparatedKeywords",value:function(e){var t=this,n=[];return e.forEach(function(e){t.opt.separateWordSearch?e.split(" ").forEach(function(e){e.trim()&&-1===n.indexOf(e)&&n.push(e)}):e.trim()&&-1===n.indexOf(e)&&n.push(e)}),{keywords:n.sort(function(e,t){return t.length-e.length}),length:n.length}}},{key:"isNumeric",value:function(e){return Number(parseFloat(e))==e}},{key:"checkRanges",value:function(e){var t=this;if(!Array.isArray(e)||"[object Object]"!==Object.prototype.toString.call(e[0]))return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(e),[];var n=[],r=0;return e.sort(function(e,t){return e.start-t.start}).forEach(function(e){var i=t.callNoMatchOnInvalidRanges(e,r),o=i.start,a=i.end;i.valid&&(e.start=o,e.length=a-o,n.push(e),r=a)}),n}},{key:"callNoMatchOnInvalidRanges",value:function(e,t){var n=void 0,r=void 0,i=!1;return e&&void 0!==e.start?(r=(n=parseInt(e.start,10))+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&r-t>0&&r-n>0?i=!0:(this.log("Ignoring invalid or overlapping range: "+JSON.stringify(e)),this.opt.noMatch(e))):(this.log("Ignoring invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:n,end:r,valid:i}}},{key:"checkWhitespaceRanges",value:function(e,t,n){var r=void 0,i=!0,o=n.length,a=t-o,s=parseInt(e.start,10)-a;return(r=(s=s>o?o:s)+parseInt(e.length,10))>o&&(r=o,this.log("End range automatically set to the max value of "+o)),s<0||r-s<0||s>o||r>o?(i=!1,this.log("Invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)):""===n.substring(s,r).replace(/\s+/g,"")&&(i=!1,this.log("Skipping whitespace only range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:s,end:r,valid:i}}},{key:"getTextNodes",value:function(e){var t=this,n="",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,function(e){r.push({start:n.length,end:(n+=e.textContent).length,node:e})},function(e){return t.matchesExclude(e.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},function(){e({value:n,nodes:r})})}},{key:"matchesExclude",value:function(e){return i.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}},{key:"wrapRangeInTextNode",value:function(e,t,n){var r=this.opt.element?this.opt.element:"mark",i=e.splitText(t),o=i.splitText(n-t),a=document.createElement(r);return a.setAttribute("data-markjs","true"),this.opt.className&&a.setAttribute("class",this.opt.className),a.textContent=i.textContent,i.parentNode.replaceChild(a,i),o}},{key:"wrapRangeInMappedTextNode",value:function(e,t,n,r,i){var o=this;e.nodes.every(function(a,s){var c=e.nodes[s+1];if(void 0===c||c.start>t){if(!r(a.node))return!1;var u=t-a.start,l=(n>a.end?a.end:n)-a.start,h=e.value.substr(0,a.start),f=e.value.substr(l+a.start);if(a.node=o.wrapRangeInTextNode(a.node,u,l),e.value=h+f,e.nodes.forEach(function(t,n){n>=s&&(e.nodes[n].start>0&&n!==s&&(e.nodes[n].start-=l),e.nodes[n].end-=l)}),n-=l,i(a.node.previousSibling,a.start),!(n>a.end))return!1;t=a.end}return!0})}},{key:"wrapGroups",value:function(e,t,n,r){return r((e=this.wrapRangeInTextNode(e,t,t+n)).previousSibling),e}},{key:"separateGroups",value:function(e,t,n,r,i){for(var o=t.length,a=1;a-1&&r(t[a],e)&&(e=this.wrapGroups(e,s,t[a].length,i))}return e}},{key:"wrapMatches",value:function(e,t,n,r,i){var o=this,a=0===t?0:t+1;this.getTextNodes(function(t){t.nodes.forEach(function(t){t=t.node;for(var i=void 0;null!==(i=e.exec(t.textContent))&&""!==i[a];){if(o.opt.separateGroups)t=o.separateGroups(t,i,a,n,r);else{if(!n(i[a],t))continue;var s=i.index;if(0!==a)for(var c=1;c + + + + + OpenCV/cv2 - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

OpenCV/cv2 Functions

+

See vidformer.cv2 API docs.

+
+

⚠️ The cv2 module is a work in progress. If you find a bug or need a missing feature implemented feel free to file an issue or contribute yourself!

+
+

Legend:

+
    +
  • ✅ - Support
  • +
  • 🔸 - Support via OpenCV cv2
  • +
  • ❌ - Not yet implemented
  • +
+

Vidformer-specific Functions

+
    +
  • cv2.vidplay(video2) - Play a VideoWriter, Spec, or Source
  • +
  • VideoWriter.spec() - Return the Spec of an output video
  • +
  • Frame.numpy() - Return the frame as a numpy array
  • +
  • cv2.setTo - The OpenCV Mat.setTo function (not in cv2)
  • +
+

opencv

+
+ + + +
ClassStatus
VideoCapture
VideoWriter
VideoWriter_fourcc
+
+ + +
FunctionStatus
imread
imwrite
+
+

opencv.imgproc

+

Drawing Functions:

+
+ + + + + + + + + + + + + + + +
FunctionStatus
arrowedLine
circle
clipLine
drawContours
drawMarker
ellipse
ellipse2Poly
fillConvexPoly
fillPoly
getFontScaleFromHeight🔸
getTextSize🔸
line
polylines
putText
rectangle
+
+

opencv.core

+
+ +
FunctionStatus
addWeighted
+
+
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/print.html b/print.html new file mode 100644 index 0000000..f6f6fb0 --- /dev/null +++ b/print.html @@ -0,0 +1,871 @@ + + + + + + vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

vidformer - Video Data Transformation

+

Test +PyPI version +Crates.io Version +Open In Colab +License

+

A research project providing infrastructure for video interfaces and pipelines. +Developed by the OSU Interactive Data Systems Lab.

+

🎯 Why vidformer

+

Vidformer efficiently transforms video data, enabling faster annotation, editing, and processing of video data—without having to focus on performance.

+

It uses a declarative specification format to represent transformations. This enables:

+
    +
  • +

    ⚡ Transparent Optimization: Vidformer optimizes the execution of declarative specifications just like a relational database optimizes relational queries.

    +
  • +
  • +

    ⏳ Lazy/Deferred Execution: Video results can be retrieved on-demand, allowing for practically instantaneous playback of video results.

    +
  • +
  • +

    🔄 Transpilation: Vidformer specifications can be created from existing code (like cv2).

    +
  • +
+

🚀 Quick Start

+

Open In Colab

+

The easiest way to get started is using vidformer's cv2 frontend, which allows most Python OpenCV visualization scripts to replace import cv2 with import vidformer.cv2 as cv2:

+
import vidformer.cv2 as cv2
+
+cap = cv2.VideoCapture("my_input.mp4")
+fps = cap.get(cv2.CAP_PROP_FPS)
+width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+out = cv2.VideoWriter("my_output.mp4", cv2.VideoWriter_fourcc(*"mp4v"),
+                        fps, (width, height))
+while True:
+    ret, frame = cap.read()
+    if not ret:
+      break
+
+    cv2.putText(frame, "Hello, World!", (100, 100), cv2.FONT_HERSHEY_SIMPLEX,
+                1, (255, 0, 0), 1)
+    out.write(frame)
+
+cap.release()
+out.release()
+
+

You can find details on this in our Getting Started Guide.

+

📘 Documentation

+ +

🔍 About the project

+

Vidformer is a highly modular suite of tools that work together; these are detailed here.

+

❌ vidformer is NOT:

+
    +
  • A conventional video editor (like Premiere Pro or Final Cut)
  • +
  • A video database/VDBMS
  • +
  • A natural language query interface for video
  • +
  • A computer vision library (like OpenCV)
  • +
  • A computer vision AI model (like CLIP or Yolo)
  • +
+

However, vidformer is highly complementary to each of these. +If you're working on any of the later four, vidformer may be for you.

+

File Layout:

+ +

License: Vidformer is open source under Apache-2.0. +Contributions welcome.

+

Getting Started

+ +

Install

+

Using vidformer requires the Python client library, vidformer-py, and a yrden server which is distributed through vidformer-cli.

+

vidformer-py

+
pip install vidformer
+
+

vidformer-cli

+

🐳 Docker:

+
docker pull dominikwinecki/vidformer:latest
+docker run --rm -it -p 8000:8000 dominikwinecki/vidformer:latest yrden --print-url
+
+

This launches a vidformer yrden server, which is our reference server implementation for local usage, on port 8000. +If you want to read or save video files locally add -v /my/local/dir:/data and then reference them as /data in the code.

+

To use:

+
import vidformer as vf
+server = vf.YrdenServer(domain="localhost", port=8000)
+
+# or for cv2
+import vidformer.cv2 as cv2
+cv2.set_cv2_server(server)
+
+

Precompiled binary:

+

Precompiled binaries are available for vidformer releases.

+

For example:

+
wget https://github.com/ixlab/vidformer/releases/download/<version>/vidformer-cli-ubuntu22.04-amd64
+sudo mv  vidformer-cli-ubuntu22.04-amd64 /usr/local/bin/vidformer-cli
+sudo chmod +x /usr/local/bin/vidformer-cli
+sudo apt install -y libopencv-dev libfdk-aac-dev
+
+

To use:

+
import vidformer as vf
+server = vf.YrdenServer(bin="vidformer-cli")
+
+

or

+
export VIDFORMER_BIN='vidformer-cli'
+
+
import vidformer as vf
+server = vf.YrdenServer()
+
+

Build from Sources

+

vidformer-cli can be compiled from our git repo with a standard cargo build.

+

This depends on the core vidformer library which itself requires linking to FFmpeg and OpenCV. +Details are available here.

+

Getting Started - cv2

+

This is a walkthrough of getting started with vidformer OpenCV cv2 compatability layer.

+
+

⚠️ Adding cv2 functions is a work in progress. See the cv2 filters page for which functions have been implemented.

+
+

Installation

+

See Installation guide

+

Or you can Open In Colab.

+
+

⚠️ Due to how Colab networking works, vidformer can't stream/play results in Colab, only save them to disk. cv2.vidplay() will not work!

+
+

Hello, world!

+

Copy in your video, or use ours:

+
curl -O https://f.dominik.win/data/dve2/tos_720p.mp4
+
+

Then just replace import cv2 with import vidformer.cv2 as cv2. +Here's our example script:

+
import vidformer.cv2 as cv2
+
+cap = cv2.VideoCapture("tos_720p.mp4")
+fps = cap.get(cv2.CAP_PROP_FPS)
+width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+out = cv2.VideoWriter("output.mp4", cv2.VideoWriter_fourcc(*"mp4v"),
+                        fps, (width, height))
+while True:
+    ret, frame = cap.read()
+    if not ret:
+      break
+
+    cv2.putText(frame, "Hello, World!", (100, 100), cv2.FONT_HERSHEY_SIMPLEX,
+                1, (255, 0, 0), 1)
+    out.write(frame)
+
+cap.release()
+out.release()
+
+

Stream the Results

+

Saving videos to disk works, but we can also display them in the notebook. +Since we stream the results and only render them on demand this can start practically instantly!

+

First, replace "output.mp4" with None to skip writing the video to disk. +Then you can use cv2.vidplay() to play the video!

+
import vidformer.cv2 as cv2
+
+cap = cv2.VideoCapture("tos_720p.mp4")
+fps = cap.get(cv2.CAP_PROP_FPS)
+width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+out = cv2.VideoWriter(None, cv2.VideoWriter_fourcc(*"mp4v"),
+                        fps, (width, height))
+while True:
+    ret, frame = cap.read()
+    if not ret:
+      break
+
+    cv2.putText(frame, "Hello, World!", (100, 100), cv2.FONT_HERSHEY_SIMPLEX,
+                1, (255, 0, 0), 1)
+    out.write(frame)
+
+cap.release()
+out.release()
+
+cv2.vidplay(out)
+
+
+

⚠️ By default cv2.vidplay() will return a video which plays in a Jupyter Notebook. If running outside a jupyter notebook you can pass method="link" to return a link instead.

+
+

Getting Started - DSL

+

This is a walkthrough of getting started with vidformer-py core DSL.

+

Installation

+

See Installation guide

+

Hello, world!

+
+

⚠️ We assume this is in a Jupyter notebook. If not then .play() won't work and you have to use .save() instead.

+
+

We start by connecting to a server and registering a source:

+
import vidformer as vf
+from fractions import Fraction
+
+server = vf.YrdenServer(domain='localhost', port=8000)
+
+tos = vf.Source(
+    server,
+    "tos_720p",     # name (for pretty printing)
+    "https://f.dominik.win/data/dve2/tos_720p.mp4",
+    stream=0,       # index of the video stream we want to use
+)
+
+print(tos.ts())
+print(tos.fmt())
+
+

This will print the timestamps of all the frames in the video, and then format information: +This may take a few seconds the first time, but frame times are cached afterwords.

+
> [Fraction(0, 1), Fraction(1, 24), Fraction(1, 12), Fraction(1, 8), ...]
+> {'width': 1280, 'height': 720, 'pix_fmt': 'yuv420p'}
+
+

Now lets create a 30 second clip starting at the 5 minute mark. +The source video is at at a constant 24 FPS, so lets create a 24 FPS output as well:

+
domain = [Fraction(i, 24) for i in range(24 * 30)]
+
+

Now we need to render each of these frames, so we define a render function.

+
def render(t: Fraction, i: int):
+    clip_start_point = Fraction(5 * 60, 1) # start at 5 * 60 seconds
+    return tos[t + clip_start_point]
+
+

We used timestamp-based indexing here, but you can also use integer indexing (tos.iloc[i + 5 * 60 * 24]).

+

Now we can create a spec and play it in the browser. +We create a spec from the resulting video's frame timestamps (domain), a function to construct each output frame (render), and the output videos format (matching tos.fmt()).

+
spec = vf.Spec(domain, render, tos.fmt())
+spec.play(server)
+
+

This plays this result: +

+
+

Some Jupyter environments are weird (i.e., VS Code), so .play() might not work. Using .play(..., method="iframe") may help.

+
+

It's worth noting that we are playing frames in order here and outputing video at the same framerate we recieved, but that doesn't need to be the case. +Here are some things other things you can now try:

+
    +
  • Reversing the video
  • +
  • Double the speed of the video +
      +
    • Either double the framerate or sample every other frame
    • +
    +
  • +
  • Shuffle the frames into a random order
  • +
  • Combining frames from multiple videos
  • +
  • Create a variable frame rate video +
      +
    • Note: .play() will not work with VFR, but .save() will.
    • +
    +
  • +
+

Bounding Boxes

+

Now let's overlay some bouding boxes over the entire clip:

+
# Load some data
+import urllib.request, json 
+with urllib.request.urlopen("https://f.dominik.win/data/dve2/tos_720p-objects.json") as r:
+    detections_per_frame = json.load(r)
+
+bbox = vf.Filter("BoundingBox") # load the built-in BoundingBox filter
+
+domain = tos.ts() # output should have same frame timestamps as our example clip
+
+def render(t, i):
+    return bbox(
+        tos[t],
+        bounds=detections_per_frame[i])
+
+spec = vf.Spec(domain, render, tos.fmt())
+spec.play(server)
+
+

This plays this result (video is just a sample clip): +

+

Composition

+

We can place frames next to each other with the HStack and VStack filters. +For example, HStack(left_frame, middle_frame, right_frame, width=1280, height=720, format="yuv420p") will place three frames side-by-side.

+

As a larger example, we can view a window function over frames as a 5x5 grid:

+
hstack = vf.Filter("HStack")
+vstack = vf.Filter("VStack")
+
+w, h = 1920, 1080
+
+def create_grid(tos, i, N, width, height, fmt="yuv420p"):
+    grid = []
+    for row in range(N):
+        columns = []
+        for col in range(N):
+            index = row * N + col
+            columns.append(tos.iloc[i + index])
+        grid.append(hstack(*columns, width=width, height=height//N, format=fmt))
+    final_grid = vstack(*grid, width=width, height=height, format=fmt)
+    return final_grid
+
+domain = [Fraction(i, 24) for i in range(0, 5000)]
+
+def render(t, i):
+    return create_grid(tos, i, 5, w, h)
+
+fmt = {'width': w, 'height': h, 'pix_fmt': 'yuv420p'}
+
+spec = vf.Spec(domain, render, fmt)
+spec.play(server)
+
+

This plays this result (video is just a sample clip): +

+

Viewing Telemetry (and User-Defined Filters)

+

This notebook shows how to build custom filters to overlay data.

+

This plays this result (video is just a sample clip): +

+

Concepts & Data Model

+

vidformer builds on the data model introduced in the V2V paper.

+
    +
  • +

    Frames are a single image. +Frames are represented as their resolution and pixel format (the type and layout of pixels in memory, such as rgb24, gray8, or yuv420p).

    +
  • +
  • +

    Videos are sequences of frames represented as an array. +We index these arrays by rational numbers corresponding to their timestamp.

    +
  • +
  • +

    Filters are functions which construct a frame. +Filters can take inputs, such as frames or data. +For example, DrawText may draw some text on a frame.

    +
  • +
  • +

    Specs declarativly represent a video synthesis task. +They represent the construction of a result videos, which is itself modeled as an array.

    +
      +
    • Specs primairly contan domain and render functions. +
        +
      • A spec's domain function returns the timestamps of the output frames.
      • +
      • A spec's render function returns a composition of filters used to construct a frame at a spesific timestamp.
      • +
      +
    • +
    +
  • +
  • +

    Data Arrays allow using data in specs symbolically, as opposed to inserting constants directly into the spec. +These allow for deduplication and loading large data blobs efficiently.

    +
      +
    • Data Arrays can be backed by external data sources, such as SQL databases.
    • +
    +
  • +
+

The vidformer Tools

+

vidformer is a highly modular suite of tools that work together:

+
    +
  • +

    vidformer-py: A Python 🐍 client for declarative video synthesis

    +
      +
    • Provides an easy-to-use library for symbolically representing transformed videos
    • +
    • Acts as a client for a VoD server (i.e., for yrden)
    • +
    • Using vidformer-py is the best place to get started
    • +
    +
  • +
  • +

    libvidformer: The core data-oriented declarative video editing library

    +
      +
    • An embedded video processing execution engine with low-level interfaces
    • +
    • Systems code, written in Rust 🦀
    • +
    • You should use if: You are building a VDBMS or other multimodal data-system infrastructure.
    • +
    • You should not use if: You just want to use vidformer in your workflows or projects.
    • +
    +
  • +
  • +

    yrden: A vidformer Video-on-Demand server

    +
      +
    • Provides vidformer services over a REST-style API
    • +
    • Allows for client libraries to be written in any language
    • +
    • Serves video results via HLS streams
    • +
    • Designed for local single-tenant use
    • +
    • You should use if: You want to create faster video results in your workflows or projects.
    • +
    • Note that yrden servers may be spun up transparently by client libraries, so you might use yrden without realizing it.
    • +
    +
  • +
  • +

    igni: A planned scale-out Video-on-Demand server

    +
      +
    • Will allow for scalable and secure public-facing VOD endpoints
    • +
    +
  • +
+

Client libraries in other languages: +Writing a vidformer client library for other languages is simple. +It's a few hundred lines of code, and you just have to construct some JSON. +Contributions or suggestions for other languages are welcome.

+

Other VoD servers: +We provide yrden as a simple reference VoD server implementation. +If you want to scale-out deployments, multi-tenant deployments, or deep integration with a specific system, writing another VoD server is needed. (In progress work)

+

vidformer-py

+

PyPI version +License

+

vidformer-py is a Python 🐍 interface for vidformer. +Our getting started guide explains how to use it.

+

Quick links:

+ +

Publish:

+
 export FLIT_USERNAME='__token__' FLIT_PASSWORD='<token>'
+flit publish
+
+

vidformer - Video Data Transformation Library

+

Crates.io Version +License

+

(lib)vidformer is a core video synthesis/transformation library. +It handles the movement, control flow, and processing of video and conventional (non-video) data.

+

Quick links:

+ +

About

+
    +
  • It's written in Rust 🦀 +
      +
    • So it does some fancy parallel processing and does so safely
    • +
    +
  • +
  • Uses the FFmpeg libav libraries for multimedia stuff +
      +
    • So it should work with nearly every video file ever made
    • +
    +
  • +
  • Uses Apache OpenDAL for I/O +
      +
    • So it can access videos in a bunch of storage services
    • +
    +
  • +
  • Implements filters using OpenCV
  • +
+

Building

+

This crate requires linking with FFmpeg, as detailed in the rusty_ffmpeg crate. +We currently target FFmpeg 7.0.

+

Filters

+ +

Built-in Filters

+

While most applications will use user-defined filters, vidformer ships with a handful of built-in filters to get you started:

+

DrawText

+

DrawText does exactly what it sounds like: draw text on a frame.

+

For example:

+
DrawText(frame, text="Hello, world!", x=100, y=100, size=48, color="white")
+
+

BoundingBox

+

BoundingBox draws bounding boxes on a frame.

+

For example:

+
BoundingBox(frame, bounds=obj)
+
+

Where obj is JSON with this schema:

+
[
+  {
+    "class": "person",
+    "confidence": 0.916827917098999,
+    "x1": 683.0721842447916,
+    "y1": 100.92174338626751,
+    "x2": 1006.863525390625,
+    "y2": 720
+  },
+  {
+    "class": "dog",
+    "confidence": 0.902531921863556,
+    "x1": 360.8750813802083,
+    "y1": 47.983140622720974,
+    "x2": 606.76171875,
+    "y2": 717.9591837897462
+  }
+]
+
+

Scale

+

The Scale filter transforms one frame type to another. +It changes both resolution and pixel format. +This is the most important filter and is essential for building with vidformer.

+

Arguments:

+
Scale(
+    frame: Frame,
+    width: int = None,
+    height: int = None,
+    pix_fmt: str = None)
+
+

By default missing width, height and format values are set to match frame. +pix_fmt must match ffmpeg's name for a pixel format.

+

For example:

+
frame = Scale(frame, width=1280, height=720, pix_fmt="rgb24")
+
+

IPC

+

IPC allows for calling User-Defined Filters (UDFs) running on the same system. +It is an infrastructure-level filter and is used to implement other filters. +It is configured with a socket and func, the filter's name, both strings.

+

The IPC filter can not be directly invoked, rather IPC filters are constructed by a server upon request. +This can be difficult, but vidformer-py handles this for you. +As of right now IPC only supports rgb24 frames.

+

HStack & VStack

+

HStack & VStack allow for composing multiple frames together, stacking them either horizontally or vertically. +It tries to automatically find a reasonable layout.

+

Arguments:

+
HStack(
+    *frames: list[Frame],
+    width: int,
+    height: int,
+    format: str)
+
+

At least one frame is required, along with a width, height and format.

+

For example:

+
compilation = HStack(left_frame, right_frame, width=1280, height=720, format="rgb24")
+
+

OpenCV/cv2 Functions

+

See vidformer.cv2 API docs.

+
+

⚠️ The cv2 module is a work in progress. If you find a bug or need a missing feature implemented feel free to file an issue or contribute yourself!

+
+

Legend:

+
    +
  • ✅ - Support
  • +
  • 🔸 - Support via OpenCV cv2
  • +
  • ❌ - Not yet implemented
  • +
+

Vidformer-specific Functions

+
    +
  • cv2.vidplay(video2) - Play a VideoWriter, Spec, or Source
  • +
  • VideoWriter.spec() - Return the Spec of an output video
  • +
  • Frame.numpy() - Return the frame as a numpy array
  • +
  • cv2.setTo - The OpenCV Mat.setTo function (not in cv2)
  • +
+

opencv

+
+ + + +
ClassStatus
VideoCapture
VideoWriter
VideoWriter_fourcc
+
+ + +
FunctionStatus
imread
imwrite
+
+

opencv.imgproc

+

Drawing Functions:

+
+ + + + + + + + + + + + + + + +
FunctionStatus
arrowedLine
circle
clipLine
drawContours
drawMarker
ellipse
ellipse2Poly
fillConvexPoly
fillPoly
getFontScaleFromHeight🔸
getTextSize🔸
line
polylines
putText
rectangle
+
+

opencv.core

+
+ +
FunctionStatus
addWeighted
+

User-Defined Filters

+

To implement a new user-defined filter (UDF) you need to host a filter server over a UNIX Domain Socket. +The vidformer-py library makes this easy.

+

Filters take some combination of frames and data (string, int, bool) and return a single frame result. +The vidformer project uses Python-style arguments, allowing ordered and named arguments (*args and **kwargs style).

+

To do this we define a new filter class and host it:

+
import vidformer as vf
+import cv2
+
+class MyFilter(vf.UDF):
+
+    def filter(self, frame: vf.UDFFrame, name: str):
+        """Return the result frame."""
+
+        text = f"Hello, {name}!"
+
+        image = frame.data().copy()
+        cv2.putText(
+		    image,
+            text, 
+            (100,100),
+            cv2.FONT_HERSHEY_SIMPLEX,
+            1,
+            (255, 0, 0),
+            1,
+        )
+        return vf.UDFFrame(image, frame.frame_type())
+
+    def filter_type(self, frame: vf.UDFFrameType, _name: str):
+        """Returns the type of the output frame."""
+        return frame
+
+mf_udf = MyFilter("MyFilter") # name used for pretty printing
+
+my_filter = mf_udf.into_filter() # host the UDF in a subprocess, returns a vf.Filter
+
+

Now we can use our newly-created filter in specs: my_filter(some_frame, "vidformer").

+

There is a catch, UDFs currently only support rgb24 pixel formats. +So invoking my_filter will need to convert around this:

+
scale = vf.Filter('Scale')
+
+def render(t, i):
+    f = scale(tos[t], pix_fmt="rgb24", width=1280, height=720)
+    f = my_filter(f, "world")
+    f = scale(f, pix_fmt="yuv420p", width=1280, height=720)
+    return f
+
+

Roadmap

+

An unordered list of potential future features:

+
    +
  • +

    Igni - A scale-out multi-tenant vidformer server in the cloud

    +
  • +
  • +

    Supervision Integration

    +
  • +
  • +

    Full GPU Acceleration

    +
  • +
  • +

    WebAssembly Builds

    +
  • +
  • +

    WebAssembly user defined filters & specs

    +
  • +
+

FAQ

+

What video formats does vidformer support?

+

In short, essentially everything. +vidformer uses the FFmpeg/libav* libraries internally, so any media FFmpeg works with should work in vidformer as well. +We support many container formats (e.g., mp4, mov) and codecs (e.g., H.264, VP8).

+

A full list of supported codecs enabled in a vidformer build can be found by running:

+
vidformer-cli codecs
+
+

Can I access remote videos on the internet?

+

Yes, vidformer uses Apache OpenDAL for I/O, so most common data/storage access protocols are supported. +However, not all storage services are enabled in distributed binaries. +We guarantee that HTTP, S3, and the local filesystem always work.

+

How does vidformer compare to FFmpeg?

+

vidformer is far more expressive than the FFmpeg filter interface. +Mainly, vidformer is designed for work around data, so edits are created programatically and edits can reference data. +Also, vidformer enables serving resut videos on demand.

+

vidformer uses the FFmpeg/libav* libraries internally, so any media FFmpeg works with should also work in vidformer.

+

How does vidformer compare to OpenCV/cv2?

+

vidformer orchestrates data movment in video synthesis tasks, but does not implement image processing directly. +Most use cases will still use OpenCV for this.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + +
+ + diff --git a/roadmap.html b/roadmap.html new file mode 100644 index 0000000..bc0b975 --- /dev/null +++ b/roadmap.html @@ -0,0 +1,228 @@ + + + + + + Roadmap - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

Roadmap

+

An unordered list of potential future features:

+
    +
  • +

    Igni - A scale-out multi-tenant vidformer server in the cloud

    +
  • +
  • +

    Supervision Integration

    +
  • +
  • +

    Full GPU Acceleration

    +
  • +
  • +

    WebAssembly Builds

    +
  • +
  • +

    WebAssembly user defined filters & specs

    +
  • +
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/search-index.js b/search-index.js new file mode 100644 index 0000000..bf9bbe2 --- /dev/null +++ b/search-index.js @@ -0,0 +1,4 @@ +var searchIndex = new Map(JSON.parse('[["vidformer",{"t":"PFFPFFGPPPPPPPFGPPFPPCNNNNNNNNNNNNNNNNNNNNNNNNNNNNOHHOOOONNOOCONNNNNNOOOONNNNNNNNOOHNNNNNNNNOOOONOOOOHONNNCCCCNONNNNNNNNNNNNNNNNNNNNNONNNNNNNNHNNNNNNNNKFNNNMNNNMNMNNNNNNNPPKPFPFPPPPGNNNNNNCNNNNNNNNNCNNNMMNNNOONNNNOONNNNNNNNNNNNNNNNNNNNNNOOFFFFFFFFFFFFFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFFFFFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFNNNNNNNNNNNNNNNNNPPPPGGPFPPGFPGPPPPPONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFFNNNNNNNOHNNOONNNNNNOOONONNOONNNNNONNNNNFKKNNNMNNONNMNNNNNN","n":["AVError","CodecDescriptor","Config","ConfigError","Context","EncoderConfig","Error","FilterInternalError","IOError","IndexOutOfBounds","InvalidFilterArgType","InvalidFilterArgValue","InvalidOutputFrameType","MissingFilterArg","Range","RangeTsFormat","SegmentLocal","SourceNotFound","Stats","StreamLocal","Unknown","array","borrow","","","","","","","","borrow_mut","","","","","","","","clone","","","","clone_into","","","","clone_to_uninit","","","","codec_name","codecs","create_spec_hls","decode_pool_size","decoder_view","decoders","decoders_created","deserialize","","encoder","end","filter","filterers","fmt","","","","","","format","format_id_pretty_name","frames_decoded","frames_written","from","","","","","","","","has_decoder","has_encoder","init","into","","","","","","","","long_name","max_decoder_count","max_encode_buffer_size","name","new","opts","output_height","output_pix_fmt","output_width","run","runtime","serialize","","","service","sir","source","spec","spec_ctx","start","to_owned","","","","to_string","try_from","","","","","","","","try_into","","","","","","","","ts_format","type_id","","","","","","","","validate","vzip","","","","","","","","Array","JsonArary","borrow","borrow_mut","deserialize","domain","","fmt","from","index","","index_t","","into","serialize","try_from","try_into","type_id","vzip","Bool","Bytes","Filter","Float","Frame","","FrameType","","Int","List","String","Val","borrow","","","borrow_mut","","","builtin","clone","","","clone_into","","","clone_to_uninit","","","cv2","deserialize","","eq","filter","filter_type","fmt","","","format","","from","","","from_expr","height","","into","","","new","serialize","","","to_owned","","","try_from","","","try_into","","","type_id","","","vzip","","","width","","Annotate","BoundingBox","BoundingBoxBound","Box","DrawBox","DrawText","HStack","IPC","InlineMat","Pad","PlaceholderFrame","Scale","SliceMat","SliceWriteMat","VStack","borrow","","","","","","","","","","","","","","","borrow_mut","","","","","","","","","","","","","","","deserialize","filter","","","","","","","","","","","","","","filter_type","","","","","","","","","","","","","","filters","fmt","from","","","","","","","","","","","","","","","into","","","","","","","","","","","","","","","new","try_from","","","","","","","","","","","","","","","try_into","","","","","","","","","","","","","","","type_id","","","","","","","","","","","","","","","via_map","vzip","","","","","","","","","","","","","","","AddWeighted","ArrowedLine","Circle","Line","PutText","Rectangle","SetTo","borrow","","","","","","","borrow_mut","","","","","","","filter","","","","","","","filter_type","","","","","","","filters","from","","","","","","","into","","","","","","","try_from","","","","","","","try_into","","","","","","","type_id","","","","","","","vzip","","","","","","","Service","borrow","borrow_mut","clone","clone_into","clone_to_uninit","default","deserialize","fmt","from","into","new","serialize","to_owned","try_from","try_into","type_id","vzip","ArrayRef","Bool","Bytes","Data","DataExpr","Expr","Filter","FilterExpr","Float","Frame","FrameExpr","FrameSource","ILoc","IndexConst","Int","List","Source","String","T","args","borrow","","","","","","borrow_mut","","","","","","clone","","","","","","clone_into","","","","","","clone_to_uninit","","","","","","cmp","","deserialize","","","","","","eq","","fmt","","","","","","","","","","from","","","","","","index","into","","","","","","kwargs","name","new","partial_cmp","","serialize","","","","","","to_owned","","","","","","to_string","","","","try_from","","","","","","try_into","","","","","","type_id","","","","","","video","vzip","","","","","","SourceFileMeta","SourceVideoStreamMeta","borrow","","borrow_mut","","clone","clone_into","clone_to_uninit","codec","create_profile_file","deserialize","","file_path","file_size","fmt","","from","","into","","keys","name","pix_fmt","profile","resolution","serialize","","service","stream_idx","to_owned","try_from","","try_into","","ts","type_id","","validate","vzip","","JsonSpec","Spec","SpecContext","borrow","borrow_mut","deserialize","domain","","fmt","frames","from","into","render","","serialize","try_from","try_into","type_id","vzip"],"q":[[0,"vidformer"],[151,"vidformer::array"],[170,"vidformer::filter"],[239,"vidformer::filter::builtin"],[407,"vidformer::filter::cv2"],[485,"vidformer::service"],[503,"vidformer::sir"],[632,"vidformer::source"],[673,"vidformer::spec"],[692,"vidformer::dve"],[693,"vidformer::util"],[694,"alloc::vec"],[695,"alloc::string"],[696,"num_rational"],[697,"core::result"],[698,"serde::de"],[699,"core::fmt"],[700,"alloc::boxed"],[701,"alloc::collections::btree::map"],[702,"alloc::sync"],[703,"core::option"],[704,"serde::ser"],[705,"core::any"],[706,"rusty_ffmpeg::ffi"],[707,"vidformer::filter::builtin::ipc"],[708,"std::collections::hash::map"],[709,"core::cmp"]],"i":"Bd``0```0000000``j1`01`Ah2fhBj4lA`574326104361436143613``44424341`477432040225743261000`57432610022053444`2432````51436175743261057432610157432610`57432610``D`00Bn1110101111111Dh0`0`0`0000`Df1Dj120`120120120`100Cd023121231321231123123123123123123121```````````````EdEfEhEjElEnF`FbFdFfFhFjFlFnEb>=<;:98765432100>=<;:987654321>=<;:987654321`0>=<;:9876543210>=<;:9876543210>>=<;:9876543210>=<;:9876543210>=<;:9876543210>>=<;:9876543210```````G`GbGdGfGhGjGl654321065432106543210`654321065432106543210654321065432106543210`Gn0000000000000000Dd00Hh``Hj`21``Hb`33130Hf1Hd14532014532014532014532014532020145320220144553320145302014531102020145320145324532014532014532014530201453``HnBl100000`100010101000000100001010010010```I`00Ad111110111111","f":"``````````````````````{b{{b{c}}}{}}0000000{{{b{d}}}{{b{dc}}}{}}0000000{{{b{f}}}f}{{{b{h}}}h}{{{b{j}}}j}{{{b{l}}}l}{{b{b{dc}}}n{}}000{bn}000`{{}{{Ab{A`}}}}{{{b{Ad}}{b{Af}}{b{Ah}}{b{f}}}{{An{AjAjAj{Ab{{An{AlAl}}}}}}}}````{c{{B`{f}}}Bb}{c{{B`{h}}}Bb}````{{{b{Bd}}{b{dBf}}}Bh}0{{{b{f}}{b{dBf}}}Bh}{{{b{h}}{b{dBf}}}Bh}{{{b{Bj}}{b{dBf}}}Bh}{{{b{A`}}{b{dBf}}}Bh}````{cc{}}0000000``{{}n}{{}c{}}0000000````{{{Ab{Bl}}{Cb{Aj{C`{Bn}}}}{Cb{Aj{C`{Cd}}}}}Ah}````{{{b{{Cf{{C`{Ad}}}}}}{b{Af}}{b{{Cf{Ah}}}}{b{{Cf{f}}}}{b{{Ch{l}}}}}{{B`{BjBd}}}}`{{{b{f}}c}B`Cj}{{{b{h}}c}B`Cj}{{{b{Bj}}c}B`Cj}````{{{b{Ah}}}{{`{Cl}}}}`{bc{}}000{bAj}{c{{B`{e}}}{}{}}0000000{{}{{B`{c}}}{}}0000000`{bCn}0000000{{{b{{Cf{{C`{Ad}}}}}}{b{{Cf{Ah}}}}{b{{Cf{f}}}}}{{B`{nBd}}}}<<<<<<<<``{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{c{{B`{D`}}}Bb}{{{b{Bn}}}{{Ab{Al}}}}{{{b{D`}}}{{Ab{Al}}}}{{{b{D`}}{b{dBf}}}Bh}{cc{}}{{{b{Bn}}Db}Dd}{{{b{D`}}Db}Dd}{{{b{Bn}}Al}Dd}{{{b{D`}}Al}Dd}{{}c{}}{{{b{D`}}c}B`Cj}{c{{B`{e}}}{}{}}{{}{{B`{c}}}{}}{bCn}4````````````???>>>`{{{b{Df}}}Df}{{{b{Dh}}}Dh}{{{b{Dj}}}Dj}{{b{b{dc}}}n{}}00{bn}00`{c{{B`{Df}}}Bb}{c{{B`{Dj}}}Bb}{{{b{Dj}}{b{Dj}}}Dl}{{{b{Cd}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Cd}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Df}}{b{dBf}}}Bh}{{{b{Dh}}{b{dBf}}}Bh}{{{b{Dj}}{b{dBf}}}Bh}``{cc{}}00{{{b{Dd}}{b{Ah}}}Dh}``{{}c{}}00{{DbDbE`}Dj}{{{b{Df}}c}B`Cj}{{{b{Dh}}c}B`Cj}{{{b{Dj}}c}B`Cj}{bc{}}00{c{{B`{e}}}{}{}}00{{}{{B`{c}}}{}}00{bCn}00888`````````````````{b{{b{c}}}{}}00000000000000{{{b{d}}}{{b{dc}}}{}}00000000000000{c{{B`{Eb}}}Bb}{{{b{Ed}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Ef}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Eh}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Ej}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{El}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{En}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{F`}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Fb}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Fd}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Ff}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Fh}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Fj}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Fl}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Fn}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Ed}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Ef}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Eh}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Ej}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{El}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{En}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{F`}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Fb}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Fd}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Ff}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Fh}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Fj}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Fl}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Fn}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{}{{Cb{Aj{C`{Cd}}}}}}{{{b{Eb}}{b{dBf}}}Bh}{cc{}}00000000000000{{}c{}}00000000000000{{AjAj}{{B`{EdBd}}}}{c{{B`{e}}}{}{}}00000000000000{{}{{B`{c}}}{}}00000000000000{bCn}00000000000000{{{b{{Cb{AjAj}}}}}{{B`{EdBd}}}}555555555555555```````{b{{b{c}}}{}}000000{{{b{d}}}{{b{dc}}}{}}000000{{{b{G`}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Gb}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Gd}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Gf}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Gh}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Gj}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{Gl}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DfBd}}}}{{{b{G`}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Gb}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Gd}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Gf}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Gh}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Gj}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{{b{Gl}}{b{{Dn{Dh}}}}{b{{Cb{AjDh}}}}}{{B`{DjBd}}}}{{}{{Cb{Aj{C`{Cd}}}}}}{cc{}}000000{{}c{}}000000{c{{B`{e}}}{}{}}000000{{}{{B`{c}}}{}}000000{bCn}0000003333333`{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{{{b{Gn}}}Gn}{{b{b{dc}}}n{}}{bn}{{}Gn}{c{{B`{Gn}}}Bb}{{{b{Gn}}{b{dBf}}}Bh}<;{{Aj{H`{AjAj}}}Gn}{{{b{Gn}}c}B`Cj}{bc{}}=<;>````````````````````::::::999999{{{b{Hb}}}Hb}{{{b{Hd}}}Hd}{{{b{Hf}}}Hf}{{{b{Hh}}}Hh}{{{b{Dd}}}Dd}{{{b{Hj}}}Hj}======<<<<<<{{{b{Hb}}{b{Hb}}}Hl}{{{b{Hd}}{b{Hd}}}Hl}{c{{B`{Hb}}}Bb}{c{{B`{Hd}}}Bb}{c{{B`{Hf}}}Bb}{c{{B`{Hh}}}Bb}{c{{B`{Dd}}}Bb}{c{{B`{Hj}}}Bb}{{{b{Hb}}{b{Hb}}}Dl}{{{b{Hd}}{b{Hd}}}Dl}{{{b{Hb}}{b{dBf}}}Bh}0{{{b{Hd}}{b{dBf}}}Bh}{{{b{Hf}}{b{dBf}}}Bh}{{{b{Hh}}{b{dBf}}}Bh}0{{{b{Dd}}{b{dBf}}}Bh}0{{{b{Hj}}{b{dBf}}}Bh}0{cc{}}00000{{{b{Hd}}}{{b{Hb}}}}{{}c{}}00000``{{AjHb}Hd}{{{b{Hb}}{b{Hb}}}{{Ch{Hl}}}}{{{b{Hd}}{b{Hd}}}{{Ch{Hl}}}}{{{b{Hb}}c}B`Cj}{{{b{Hd}}c}B`Cj}{{{b{Hf}}c}B`Cj}{{{b{Hh}}c}B`Cj}{{{b{Dd}}c}B`Cj}{{{b{Hj}}c}B`Cj}{bc{}}00000{bAj}000{c{{B`{e}}}{}{}}00000{{}{{B`{c}}}{}}00000{bCn}00000{{{b{Hd}}}{{b{Af}}}}??????``{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{{b{Bl}}}Bl}{{b{b{dc}}}n{}}{bn}`{{{b{{Dn{Bl}}}}}Hn}{c{{B`{Hn}}}Bb}{c{{B`{Bl}}}Bb}``{{{b{Hn}}{b{dBf}}}Bh}{{{b{Bl}}{b{dBf}}}Bh}{cc{}}0{{}c{}}0```{{{b{Af}}{b{Af}}Db{b{Gn}}}{{B`{BlBd}}}}`{{{b{Hn}}c}B`Cj}{{{b{Bl}}c}B`Cj}``{bc{}}{c{{B`{e}}}{}{}}0{{}{{B`{c}}}{}}0`{bCn}0{{{b{Af}}{b{Af}}Db{b{Gn}}}n}88```{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{c{{B`{I`}}}Bb}{{{b{Ad}}{b{Cl}}}{{Ab{Al}}}}{{{b{I`}}{b{Cl}}}{{Ab{Al}}}}{{{b{I`}}{b{dBf}}}Bh}`?>{{{b{Ad}}{b{Cl}}{b{Al}}}Hj}{{{b{I`}}{b{Cl}}{b{Al}}}Hj}{{{b{I`}}c}B`Cj}<;:{{}c{}}","D":"A@d","p":[[1,"reference"],[0,"mut"],[5,"Config",0,692],[5,"EncoderConfig",0,692],[6,"RangeTsFormat",0,692],[5,"Range",0,692],[1,"unit"],[5,"CodecDescriptor",0,693],[5,"Vec",694],[10,"Spec",673],[1,"str"],[5,"Context",0,692],[5,"String",695],[8,"Rational64",696],[1,"tuple"],[6,"Result",697],[10,"Deserializer",698],[6,"Error",0,692],[5,"Formatter",699],[8,"Result",699],[5,"Stats",0,692],[5,"SourceVideoStreamMeta",632],[10,"Array",151],[5,"Box",700],[5,"BTreeMap",701],[10,"Filter",170],[5,"Arc",702],[6,"Option",703],[10,"Serializer",704],[10,"SpecContext",673],[5,"TypeId",705],[5,"JsonArary",151],[1,"usize"],[6,"DataExpr",503],[5,"Frame",170],[6,"Val",170],[5,"FrameType",170],[1,"bool"],[1,"slice"],[8,"AVPixelFormat",706],[5,"BoundingBoxBound",239],[5,"IPC",239,707],[5,"PlaceholderFrame",239],[5,"Annotate",239],[5,"Box",239],[5,"BoundingBox",239],[5,"DrawBox",239],[5,"Scale",239],[5,"InlineMat",239],[5,"SliceMat",239],[5,"SliceWriteMat",239],[5,"Pad",239],[5,"HStack",239],[5,"VStack",239],[5,"DrawText",239],[5,"Rectangle",407],[5,"PutText",407],[5,"ArrowedLine",407],[5,"Line",407],[5,"Circle",407],[5,"SetTo",407],[5,"AddWeighted",407],[5,"Service",485],[5,"HashMap",708],[6,"IndexConst",503],[5,"FrameSource",503],[5,"FilterExpr",503],[6,"Expr",503],[6,"FrameExpr",503],[6,"Ordering",709],[5,"SourceFileMeta",632],[5,"JsonSpec",673]],"r":[[1,693],[2,692],[4,692],[5,692],[6,692],[14,692],[15,692],[18,692],[51,693],[52,692],[83,693],[101,692],[142,692],[246,707]],"b":[[63,"impl-Display-for-Error"],[64,"impl-Debug-for-Error"],[563,"impl-Debug-for-IndexConst"],[564,"impl-Display-for-IndexConst"],[567,"impl-Display-for-Expr"],[568,"impl-Debug-for-Expr"],[569,"impl-Display-for-DataExpr"],[570,"impl-Debug-for-DataExpr"],[571,"impl-Debug-for-FrameExpr"],[572,"impl-Display-for-FrameExpr"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAADICKQABAAEABAAAAAYACAARAAEAFAABABcAHAA5AAIAPQAAAEAABQBHAAIAUgABAF0ACABnAAMAbQAAAG8AHwCQAAcAmgACAJ4AAQCiAAAApAAAAKYABgCuAAAAsAAFALcABQC+AAgAyAACAMwABQDVAAIA2wAbAPgAAgD8AD0AOwEAAFoBYADKASQA8QFMAEQCAABLAj4AjgITAKUCAgCpAgIArwIFAA=="}]]')); +if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; +else if (window.initSearch) window.initSearch(searchIndex); +//{"start":39,"fragment_lengths":[13926]} \ No newline at end of file diff --git a/search.desc/vidformer/vidformer-desc-0-.js b/search.desc/vidformer/vidformer-desc-0-.js new file mode 100644 index 0000000..09b6cf6 --- /dev/null +++ b/search.desc/vidformer/vidformer-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("vidformer", 0, "vidformer is a core video synthesis/transformation library.\nConfig for a spesific run of a vidformer spec\nA context for a spec\nA range spesifier\nSelect whether the output timestamps are local to the …\nStats from a run of a vidformer spec\nArrays provide access to data.\nList all available codecs\nCreate HLS artifacts for a spec\nThe number of frames which can be fit in the decode pool\nHow many output frames can be active at once This also …\nHow many decoders can be active at once\nConfiguration to use for output encoder\nFilters create and transform video frames\nHow many filter threads to run\nThe name of the format to use for output. If None, the …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nInstantiate FFmpeg logging\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nExecute a spec, or a range of a spec.\nServices provide access to media storage.\nSpec Intermediate Representation\nSpecs declarativly define an edited video.\nValidate that a spec can be run.\nA trait for an array\nAn array backed by a JSON file\nReturns the domain of the array.\nReturns the argument unchanged.\nReturns the value at a given positional index.\nReturns the value at a given time index.\nCalls U::from(self).\nA filter that can create a video frame from some inputs\nA decoded video frame\nA value that can be passed to a filter\nvidformer built-in filters\nvidformer cv2 filters\nCreates a video frame from some inputs\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nFilter over IPC Socket\nScale & convert pixel format of a frame\nvidformer built-in filters\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nvidformer cv2 filters\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nReturns the argument unchanged.\nCalls U::from(self).\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nA spec backed by a JSON file\nA trait for a spec\nA trait for providing information to a spec during runtime\nReturns the domain of the spec.\nReturns the argument unchanged.\nCalls U::from(self).\nReturns the “logically” rendered frame at a given time.") \ No newline at end of file diff --git a/searcher.js b/searcher.js new file mode 100644 index 0000000..dc03e0a --- /dev/null +++ b/searcher.js @@ -0,0 +1,483 @@ +"use strict"; +window.search = window.search || {}; +(function search(search) { + // Search functionality + // + // You can use !hasFocus() to prevent keyhandling in your key + // event handlers while the user is typing their search. + + if (!Mark || !elasticlunr) { + return; + } + + //IE 11 Compatibility from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith + if (!String.prototype.startsWith) { + String.prototype.startsWith = function(search, pos) { + return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; + }; + } + + var search_wrap = document.getElementById('search-wrapper'), + searchbar = document.getElementById('searchbar'), + searchbar_outer = document.getElementById('searchbar-outer'), + searchresults = document.getElementById('searchresults'), + searchresults_outer = document.getElementById('searchresults-outer'), + searchresults_header = document.getElementById('searchresults-header'), + searchicon = document.getElementById('search-toggle'), + content = document.getElementById('content'), + + searchindex = null, + doc_urls = [], + results_options = { + teaser_word_count: 30, + limit_results: 30, + }, + search_options = { + bool: "AND", + expand: true, + fields: { + title: {boost: 1}, + body: {boost: 1}, + breadcrumbs: {boost: 0} + } + }, + mark_exclude = [], + marker = new Mark(content), + current_searchterm = "", + URL_SEARCH_PARAM = 'search', + URL_MARK_PARAM = 'highlight', + teaser_count = 0, + + SEARCH_HOTKEY_KEYCODE = 83, + ESCAPE_KEYCODE = 27, + DOWN_KEYCODE = 40, + UP_KEYCODE = 38, + SELECT_KEYCODE = 13; + + function hasFocus() { + return searchbar === document.activeElement; + } + + function removeChildren(elem) { + while (elem.firstChild) { + elem.removeChild(elem.firstChild); + } + } + + // Helper to parse a url into its building blocks. + function parseURL(url) { + var a = document.createElement('a'); + a.href = url; + return { + source: url, + protocol: a.protocol.replace(':',''), + host: a.hostname, + port: a.port, + params: (function(){ + var ret = {}; + var seg = a.search.replace(/^\?/,'').split('&'); + var len = seg.length, i = 0, s; + for (;i': '>', + '"': '"', + "'": ''' + }; + var repl = function(c) { return MAP[c]; }; + return function(s) { + return s.replace(/[&<>'"]/g, repl); + }; + })(); + + function formatSearchMetric(count, searchterm) { + if (count == 1) { + return count + " search result for '" + searchterm + "':"; + } else if (count == 0) { + return "No search results for '" + searchterm + "'."; + } else { + return count + " search results for '" + searchterm + "':"; + } + } + + function formatSearchResult(result, searchterms) { + var teaser = makeTeaser(escapeHTML(result.doc.body), searchterms); + teaser_count++; + + // The ?URL_MARK_PARAM= parameter belongs inbetween the page and the #heading-anchor + var url = doc_urls[result.ref].split("#"); + if (url.length == 1) { // no anchor found + url.push(""); + } + + // encodeURIComponent escapes all chars that could allow an XSS except + // for '. Due to that we also manually replace ' with its url-encoded + // representation (%27). + var searchterms = encodeURIComponent(searchterms.join(" ")).replace(/\'/g, "%27"); + + return '' + result.doc.breadcrumbs + '' + + '' + + teaser + ''; + } + + function makeTeaser(body, searchterms) { + // The strategy is as follows: + // First, assign a value to each word in the document: + // Words that correspond to search terms (stemmer aware): 40 + // Normal words: 2 + // First word in a sentence: 8 + // Then use a sliding window with a constant number of words and count the + // sum of the values of the words within the window. Then use the window that got the + // maximum sum. If there are multiple maximas, then get the last one. + // Enclose the terms in . + var stemmed_searchterms = searchterms.map(function(w) { + return elasticlunr.stemmer(w.toLowerCase()); + }); + var searchterm_weight = 40; + var weighted = []; // contains elements of ["word", weight, index_in_document] + // split in sentences, then words + var sentences = body.toLowerCase().split('. '); + var index = 0; + var value = 0; + var searchterm_found = false; + for (var sentenceindex in sentences) { + var words = sentences[sentenceindex].split(' '); + value = 8; + for (var wordindex in words) { + var word = words[wordindex]; + if (word.length > 0) { + for (var searchtermindex in stemmed_searchterms) { + if (elasticlunr.stemmer(word).startsWith(stemmed_searchterms[searchtermindex])) { + value = searchterm_weight; + searchterm_found = true; + } + }; + weighted.push([word, value, index]); + value = 2; + } + index += word.length; + index += 1; // ' ' or '.' if last word in sentence + }; + index += 1; // because we split at a two-char boundary '. ' + }; + + if (weighted.length == 0) { + return body; + } + + var window_weight = []; + var window_size = Math.min(weighted.length, results_options.teaser_word_count); + + var cur_sum = 0; + for (var wordindex = 0; wordindex < window_size; wordindex++) { + cur_sum += weighted[wordindex][1]; + }; + window_weight.push(cur_sum); + for (var wordindex = 0; wordindex < weighted.length - window_size; wordindex++) { + cur_sum -= weighted[wordindex][1]; + cur_sum += weighted[wordindex + window_size][1]; + window_weight.push(cur_sum); + }; + + if (searchterm_found) { + var max_sum = 0; + var max_sum_window_index = 0; + // backwards + for (var i = window_weight.length - 1; i >= 0; i--) { + if (window_weight[i] > max_sum) { + max_sum = window_weight[i]; + max_sum_window_index = i; + } + }; + } else { + max_sum_window_index = 0; + } + + // add around searchterms + var teaser_split = []; + var index = weighted[max_sum_window_index][2]; + for (var i = max_sum_window_index; i < max_sum_window_index+window_size; i++) { + var word = weighted[i]; + if (index < word[2]) { + // missing text from index to start of `word` + teaser_split.push(body.substring(index, word[2])); + index = word[2]; + } + if (word[1] == searchterm_weight) { + teaser_split.push("") + } + index = word[2] + word[0].length; + teaser_split.push(body.substring(word[2], index)); + if (word[1] == searchterm_weight) { + teaser_split.push("") + } + }; + + return teaser_split.join(''); + } + + function init(config) { + results_options = config.results_options; + search_options = config.search_options; + searchbar_outer = config.searchbar_outer; + doc_urls = config.doc_urls; + searchindex = elasticlunr.Index.load(config.index); + + // Set up events + searchicon.addEventListener('click', function(e) { searchIconClickHandler(); }, false); + searchbar.addEventListener('keyup', function(e) { searchbarKeyUpHandler(); }, false); + document.addEventListener('keydown', function(e) { globalKeyHandler(e); }, false); + // If the user uses the browser buttons, do the same as if a reload happened + window.onpopstate = function(e) { doSearchOrMarkFromUrl(); }; + // Suppress "submit" events so the page doesn't reload when the user presses Enter + document.addEventListener('submit', function(e) { e.preventDefault(); }, false); + + // If reloaded, do the search or mark again, depending on the current url parameters + doSearchOrMarkFromUrl(); + } + + function unfocusSearchbar() { + // hacky, but just focusing a div only works once + var tmp = document.createElement('input'); + tmp.setAttribute('style', 'position: absolute; opacity: 0;'); + searchicon.appendChild(tmp); + tmp.focus(); + tmp.remove(); + } + + // On reload or browser history backwards/forwards events, parse the url and do search or mark + function doSearchOrMarkFromUrl() { + // Check current URL for search request + var url = parseURL(window.location.href); + if (url.params.hasOwnProperty(URL_SEARCH_PARAM) + && url.params[URL_SEARCH_PARAM] != "") { + showSearch(true); + searchbar.value = decodeURIComponent( + (url.params[URL_SEARCH_PARAM]+'').replace(/\+/g, '%20')); + searchbarKeyUpHandler(); // -> doSearch() + } else { + showSearch(false); + } + + if (url.params.hasOwnProperty(URL_MARK_PARAM)) { + var words = decodeURIComponent(url.params[URL_MARK_PARAM]).split(' '); + marker.mark(words, { + exclude: mark_exclude + }); + + var markers = document.querySelectorAll("mark"); + function hide() { + for (var i = 0; i < markers.length; i++) { + markers[i].classList.add("fade-out"); + window.setTimeout(function(e) { marker.unmark(); }, 300); + } + } + for (var i = 0; i < markers.length; i++) { + markers[i].addEventListener('click', hide); + } + } + } + + // Eventhandler for keyevents on `document` + function globalKeyHandler(e) { + if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey || e.target.type === 'textarea' || e.target.type === 'text' || !hasFocus() && /^(?:input|select|textarea)$/i.test(e.target.nodeName)) { return; } + + if (e.keyCode === ESCAPE_KEYCODE) { + e.preventDefault(); + searchbar.classList.remove("active"); + setSearchUrlParameters("", + (searchbar.value.trim() !== "") ? "push" : "replace"); + if (hasFocus()) { + unfocusSearchbar(); + } + showSearch(false); + marker.unmark(); + } else if (!hasFocus() && e.keyCode === SEARCH_HOTKEY_KEYCODE) { + e.preventDefault(); + showSearch(true); + window.scrollTo(0, 0); + searchbar.select(); + } else if (hasFocus() && e.keyCode === DOWN_KEYCODE) { + e.preventDefault(); + unfocusSearchbar(); + searchresults.firstElementChild.classList.add("focus"); + } else if (!hasFocus() && (e.keyCode === DOWN_KEYCODE + || e.keyCode === UP_KEYCODE + || e.keyCode === SELECT_KEYCODE)) { + // not `:focus` because browser does annoying scrolling + var focused = searchresults.querySelector("li.focus"); + if (!focused) return; + e.preventDefault(); + if (e.keyCode === DOWN_KEYCODE) { + var next = focused.nextElementSibling; + if (next) { + focused.classList.remove("focus"); + next.classList.add("focus"); + } + } else if (e.keyCode === UP_KEYCODE) { + focused.classList.remove("focus"); + var prev = focused.previousElementSibling; + if (prev) { + prev.classList.add("focus"); + } else { + searchbar.select(); + } + } else { // SELECT_KEYCODE + window.location.assign(focused.querySelector('a')); + } + } + } + + function showSearch(yes) { + if (yes) { + search_wrap.classList.remove('hidden'); + searchicon.setAttribute('aria-expanded', 'true'); + } else { + search_wrap.classList.add('hidden'); + searchicon.setAttribute('aria-expanded', 'false'); + var results = searchresults.children; + for (var i = 0; i < results.length; i++) { + results[i].classList.remove("focus"); + } + } + } + + function showResults(yes) { + if (yes) { + searchresults_outer.classList.remove('hidden'); + } else { + searchresults_outer.classList.add('hidden'); + } + } + + // Eventhandler for search icon + function searchIconClickHandler() { + if (search_wrap.classList.contains('hidden')) { + showSearch(true); + window.scrollTo(0, 0); + searchbar.select(); + } else { + showSearch(false); + } + } + + // Eventhandler for keyevents while the searchbar is focused + function searchbarKeyUpHandler() { + var searchterm = searchbar.value.trim(); + if (searchterm != "") { + searchbar.classList.add("active"); + doSearch(searchterm); + } else { + searchbar.classList.remove("active"); + showResults(false); + removeChildren(searchresults); + } + + setSearchUrlParameters(searchterm, "push_if_new_search_else_replace"); + + // Remove marks + marker.unmark(); + } + + // Update current url with ?URL_SEARCH_PARAM= parameter, remove ?URL_MARK_PARAM and #heading-anchor . + // `action` can be one of "push", "replace", "push_if_new_search_else_replace" + // and replaces or pushes a new browser history item. + // "push_if_new_search_else_replace" pushes if there is no `?URL_SEARCH_PARAM=abc` yet. + function setSearchUrlParameters(searchterm, action) { + var url = parseURL(window.location.href); + var first_search = ! url.params.hasOwnProperty(URL_SEARCH_PARAM); + if (searchterm != "" || action == "push_if_new_search_else_replace") { + url.params[URL_SEARCH_PARAM] = searchterm; + delete url.params[URL_MARK_PARAM]; + url.hash = ""; + } else { + delete url.params[URL_MARK_PARAM]; + delete url.params[URL_SEARCH_PARAM]; + } + // A new search will also add a new history item, so the user can go back + // to the page prior to searching. A updated search term will only replace + // the url. + if (action == "push" || (action == "push_if_new_search_else_replace" && first_search) ) { + history.pushState({}, document.title, renderURL(url)); + } else if (action == "replace" || (action == "push_if_new_search_else_replace" && !first_search) ) { + history.replaceState({}, document.title, renderURL(url)); + } + } + + function doSearch(searchterm) { + + // Don't search the same twice + if (current_searchterm == searchterm) { return; } + else { current_searchterm = searchterm; } + + if (searchindex == null) { return; } + + // Do the actual search + var results = searchindex.search(searchterm, search_options); + var resultcount = Math.min(results.length, results_options.limit_results); + + // Display search metrics + searchresults_header.innerText = formatSearchMetric(resultcount, searchterm); + + // Clear and insert results + var searchterms = searchterm.split(' '); + removeChildren(searchresults); + for(var i = 0; i < resultcount ; i++){ + var resultElem = document.createElement('li'); + resultElem.innerHTML = formatSearchResult(results[i], searchterms); + searchresults.appendChild(resultElem); + } + + // Display results + showResults(true); + } + + fetch(path_to_root + 'searchindex.json') + .then(response => response.json()) + .then(json => init(json)) + .catch(error => { // Try to load searchindex.js if fetch failed + var script = document.createElement('script'); + script.src = path_to_root + 'searchindex.js'; + script.onload = () => init(window.search); + document.head.appendChild(script); + }); + + // Exported functions + search.hasFocus = hasFocus; +})(window.search); diff --git a/searchindex.js b/searchindex.js new file mode 100644 index 0000000..e5ab42e --- /dev/null +++ b/searchindex.js @@ -0,0 +1 @@ +Object.assign(window.search, {"doc_urls":["introduction.html#vidformer---video-data-transformation","introduction.html#-why-vidformer","introduction.html#-quick-start","introduction.html#-documentation","introduction.html#-about-the-project","getting-started.html#getting-started","install.html#install","install.html#vidformer-py","install.html#vidformer-cli","install.html#-docker","install.html#precompiled-binary","install.html#build-from-sources","getting-started-cv2.html#getting-started---cv2","getting-started-cv2.html#installation","getting-started-cv2.html#hello-world","getting-started-cv2.html#stream-the-results","getting-started-dsl.html#getting-started---dsl","getting-started-dsl.html#installation","getting-started-dsl.html#hello-world","getting-started-dsl.html#bounding-boxes","getting-started-dsl.html#composition","getting-started-dsl.html#viewing-telemetry-and-user-defined-filters","concepts.html#concepts--data-model","tools.html#the-vidformer-tools","vidformer-py.html#vidformer-py","libvidformer.html#vidformer---video-data-transformation-library","libvidformer.html#about","libvidformer.html#building","filters.html#filters","builtin-filters.html#built-in-filters","builtin-filters.html#drawtext","builtin-filters.html#boundingbox","builtin-filters.html#scale","builtin-filters.html#ipc","builtin-filters.html#hstack--vstack","opencv-filters.html#opencvcv2-functions","opencv-filters.html#vidformer-specific-functions","opencv-filters.html#opencv","opencv-filters.html#opencvimgproc","opencv-filters.html#opencvcore","udf-filters.html#user-defined-filters","roadmap.html#roadmap","faq.html#faq","faq.html#what-video-formats-does-vidformer-support","faq.html#can-i-access-remote-videos-on-the-internet","faq.html#how-does-vidformer-compare-to-ffmpeg","faq.html#how-does-vidformer-compare-to-opencvcv2"],"index":{"documentStore":{"docInfo":{"0":{"body":21,"breadcrumbs":5,"title":4},"1":{"body":53,"breadcrumbs":2,"title":1},"10":{"body":48,"breadcrumbs":5,"title":2},"11":{"body":20,"breadcrumbs":5,"title":2},"12":{"body":19,"breadcrumbs":8,"title":3},"13":{"body":18,"breadcrumbs":6,"title":1},"14":{"body":53,"breadcrumbs":7,"title":2},"15":{"body":79,"breadcrumbs":7,"title":2},"16":{"body":7,"breadcrumbs":8,"title":3},"17":{"body":3,"breadcrumbs":6,"title":1},"18":{"body":218,"breadcrumbs":7,"title":2},"19":{"body":48,"breadcrumbs":7,"title":2},"2":{"body":62,"breadcrumbs":3,"title":2},"20":{"body":94,"breadcrumbs":6,"title":1},"21":{"body":12,"breadcrumbs":10,"title":5},"22":{"body":114,"breadcrumbs":6,"title":3},"23":{"body":176,"breadcrumbs":3,"title":2},"24":{"body":29,"breadcrumbs":5,"title":2},"25":{"body":24,"breadcrumbs":7,"title":5},"26":{"body":31,"breadcrumbs":2,"title":0},"27":{"body":11,"breadcrumbs":3,"title":1},"28":{"body":10,"breadcrumbs":2,"title":1},"29":{"body":11,"breadcrumbs":5,"title":2},"3":{"body":7,"breadcrumbs":2,"title":1},"30":{"body":14,"breadcrumbs":4,"title":1},"31":{"body":35,"breadcrumbs":4,"title":1},"32":{"body":51,"breadcrumbs":4,"title":1},"33":{"body":43,"breadcrumbs":4,"title":1},"34":{"body":39,"breadcrumbs":5,"title":2},"35":{"body":27,"breadcrumbs":4,"title":2},"36":{"body":20,"breadcrumbs":5,"title":3},"37":{"body":9,"breadcrumbs":3,"title":1},"38":{"body":19,"breadcrumbs":3,"title":1},"39":{"body":3,"breadcrumbs":3,"title":1},"4":{"body":80,"breadcrumbs":2,"title":1},"40":{"body":147,"breadcrumbs":7,"title":3},"41":{"body":25,"breadcrumbs":2,"title":1},"42":{"body":0,"breadcrumbs":2,"title":1},"43":{"body":37,"breadcrumbs":5,"title":4},"44":{"body":23,"breadcrumbs":5,"title":4},"45":{"body":35,"breadcrumbs":4,"title":3},"46":{"body":16,"breadcrumbs":4,"title":3},"5":{"body":12,"breadcrumbs":4,"title":2},"6":{"body":14,"breadcrumbs":4,"title":1},"7":{"body":3,"breadcrumbs":5,"title":2},"8":{"body":0,"breadcrumbs":5,"title":2},"9":{"body":47,"breadcrumbs":4,"title":1}},"docs":{"0":{"body":"Test PyPI version Crates.io Version Open In Colab License A research project providing infrastructure for video interfaces and pipelines. Developed by the OSU Interactive Data Systems Lab.","breadcrumbs":"Introduction » vidformer - Video Data Transformation","id":"0","title":"vidformer - Video Data Transformation"},"1":{"body":"Vidformer efficiently transforms video data, enabling faster annotation, editing, and processing of video data—without having to focus on performance. It uses a declarative specification format to represent transformations. This enables: ⚡ Transparent Optimization: Vidformer optimizes the execution of declarative specifications just like a relational database optimizes relational queries. ⏳ Lazy/Deferred Execution: Video results can be retrieved on-demand, allowing for practically instantaneous playback of video results. 🔄 Transpilation: Vidformer specifications can be created from existing code (like cv2).","breadcrumbs":"Introduction » 🎯 Why vidformer","id":"1","title":"🎯 Why vidformer"},"10":{"body":"Precompiled binaries are available for vidformer releases . For example: wget https://github.com/ixlab/vidformer/releases/download//vidformer-cli-ubuntu22.04-amd64\nsudo mv vidformer-cli-ubuntu22.04-amd64 /usr/local/bin/vidformer-cli\nsudo chmod +x /usr/local/bin/vidformer-cli\nsudo apt install -y libopencv-dev libfdk-aac-dev To use: import vidformer as vf\nserver = vf.YrdenServer(bin=\"vidformer-cli\") or export VIDFORMER_BIN='vidformer-cli' import vidformer as vf\nserver = vf.YrdenServer()","breadcrumbs":"Getting Started » Install » Precompiled binary:","id":"10","title":"Precompiled binary:"},"11":{"body":"vidformer-cli can be compiled from our git repo with a standard cargo build. This depends on the core vidformer library which itself requires linking to FFmpeg and OpenCV. Details are available here .","breadcrumbs":"Getting Started » Install » Build from Sources","id":"11","title":"Build from Sources"},"12":{"body":"This is a walkthrough of getting started with vidformer OpenCV cv2 compatability layer. ⚠️ Adding cv2 functions is a work in progress. See the cv2 filters page for which functions have been implemented.","breadcrumbs":"Getting Started » Getting Started - cv2 » Getting Started - cv2","id":"12","title":"Getting Started - cv2"},"13":{"body":"See Installation guide Or you can Open In Colab . ⚠️ Due to how Colab networking works, vidformer can't stream/play results in Colab, only save them to disk. cv2.vidplay() will not work!","breadcrumbs":"Getting Started » Getting Started - cv2 » Installation","id":"13","title":"Installation"},"14":{"body":"Copy in your video, or use ours: curl -O https://f.dominik.win/data/dve2/tos_720p.mp4 Then just replace import cv2 with import vidformer.cv2 as cv2. Here's our example script: import vidformer.cv2 as cv2 cap = cv2.VideoCapture(\"tos_720p.mp4\")\nfps = cap.get(cv2.CAP_PROP_FPS)\nwidth = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))\nheight = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) out = cv2.VideoWriter(\"output.mp4\", cv2.VideoWriter_fourcc(*\"mp4v\"), fps, (width, height))\nwhile True: ret, frame = cap.read() if not ret: break cv2.putText(frame, \"Hello, World!\", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 1) out.write(frame) cap.release()\nout.release()","breadcrumbs":"Getting Started » Getting Started - cv2 » Hello, world!","id":"14","title":"Hello, world!"},"15":{"body":"Saving videos to disk works, but we can also display them in the notebook. Since we stream the results and only render them on demand this can start practically instantly! First, replace \"output.mp4\" with None to skip writing the video to disk. Then you can use cv2.vidplay() to play the video! import vidformer.cv2 as cv2 cap = cv2.VideoCapture(\"tos_720p.mp4\")\nfps = cap.get(cv2.CAP_PROP_FPS)\nwidth = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))\nheight = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) out = cv2.VideoWriter(None, cv2.VideoWriter_fourcc(*\"mp4v\"), fps, (width, height))\nwhile True: ret, frame = cap.read() if not ret: break cv2.putText(frame, \"Hello, World!\", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 1) out.write(frame) cap.release()\nout.release() cv2.vidplay(out) ⚠️ By default cv2.vidplay() will return a video which plays in a Jupyter Notebook. If running outside a jupyter notebook you can pass method=\"link\" to return a link instead.","breadcrumbs":"Getting Started » Getting Started - cv2 » Stream the Results","id":"15","title":"Stream the Results"},"16":{"body":"This is a walkthrough of getting started with vidformer-py core DSL.","breadcrumbs":"Getting Started » Getting Started - DSL » Getting Started - DSL","id":"16","title":"Getting Started - DSL"},"17":{"body":"See Installation guide","breadcrumbs":"Getting Started » Getting Started - DSL » Installation","id":"17","title":"Installation"},"18":{"body":"⚠️ We assume this is in a Jupyter notebook. If not then .play() won't work and you have to use .save() instead. We start by connecting to a server and registering a source: import vidformer as vf\nfrom fractions import Fraction server = vf.YrdenServer(domain='localhost', port=8000) tos = vf.Source( server, \"tos_720p\", # name (for pretty printing) \"https://f.dominik.win/data/dve2/tos_720p.mp4\", stream=0, # index of the video stream we want to use\n) print(tos.ts())\nprint(tos.fmt()) This will print the timestamps of all the frames in the video, and then format information: This may take a few seconds the first time, but frame times are cached afterwords. > [Fraction(0, 1), Fraction(1, 24), Fraction(1, 12), Fraction(1, 8), ...]\n> {'width': 1280, 'height': 720, 'pix_fmt': 'yuv420p'} Now lets create a 30 second clip starting at the 5 minute mark. The source video is at at a constant 24 FPS, so lets create a 24 FPS output as well: domain = [Fraction(i, 24) for i in range(24 * 30)] Now we need to render each of these frames, so we define a render function. def render(t: Fraction, i: int): clip_start_point = Fraction(5 * 60, 1) # start at 5 * 60 seconds return tos[t + clip_start_point] We used timestamp-based indexing here, but you can also use integer indexing (tos.iloc[i + 5 * 60 * 24]). Now we can create a spec and play it in the browser. We create a spec from the resulting video's frame timestamps (domain), a function to construct each output frame (render), and the output videos format (matching tos.fmt()). spec = vf.Spec(domain, render, tos.fmt())\nspec.play(server) This plays this result: Some Jupyter environments are weird (i.e., VS Code), so .play() might not work. Using .play(..., method=\"iframe\") may help. It's worth noting that we are playing frames in order here and outputing video at the same framerate we recieved, but that doesn't need to be the case. Here are some things other things you can now try: Reversing the video Double the speed of the video Either double the framerate or sample every other frame Shuffle the frames into a random order Combining frames from multiple videos Create a variable frame rate video Note: .play() will not work with VFR, but .save() will.","breadcrumbs":"Getting Started » Getting Started - DSL » Hello, world!","id":"18","title":"Hello, world!"},"19":{"body":"Now let's overlay some bouding boxes over the entire clip: # Load some data\nimport urllib.request, json with urllib.request.urlopen(\"https://f.dominik.win/data/dve2/tos_720p-objects.json\") as r: detections_per_frame = json.load(r) bbox = vf.Filter(\"BoundingBox\") # load the built-in BoundingBox filter domain = tos.ts() # output should have same frame timestamps as our example clip def render(t, i): return bbox( tos[t], bounds=detections_per_frame[i]) spec = vf.Spec(domain, render, tos.fmt())\nspec.play(server) This plays this result (video is just a sample clip):","breadcrumbs":"Getting Started » Getting Started - DSL » Bounding Boxes","id":"19","title":"Bounding Boxes"},"2":{"body":"Open In Colab The easiest way to get started is using vidformer's cv2 frontend, which allows most Python OpenCV visualization scripts to replace import cv2 with import vidformer.cv2 as cv2: import vidformer.cv2 as cv2 cap = cv2.VideoCapture(\"my_input.mp4\")\nfps = cap.get(cv2.CAP_PROP_FPS)\nwidth = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))\nheight = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) out = cv2.VideoWriter(\"my_output.mp4\", cv2.VideoWriter_fourcc(*\"mp4v\"), fps, (width, height))\nwhile True: ret, frame = cap.read() if not ret: break cv2.putText(frame, \"Hello, World!\", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 1) out.write(frame) cap.release()\nout.release() You can find details on this in our Getting Started Guide .","breadcrumbs":"Introduction » 🚀 Quick Start","id":"2","title":"🚀 Quick Start"},"20":{"body":"We can place frames next to each other with the HStack and VStack filters. For example, HStack(left_frame, middle_frame, right_frame, width=1280, height=720, format=\"yuv420p\") will place three frames side-by-side. As a larger example, we can view a window function over frames as a 5x5 grid: hstack = vf.Filter(\"HStack\")\nvstack = vf.Filter(\"VStack\") w, h = 1920, 1080 def create_grid(tos, i, N, width, height, fmt=\"yuv420p\"): grid = [] for row in range(N): columns = [] for col in range(N): index = row * N + col columns.append(tos.iloc[i + index]) grid.append(hstack(*columns, width=width, height=height//N, format=fmt)) final_grid = vstack(*grid, width=width, height=height, format=fmt) return final_grid domain = [Fraction(i, 24) for i in range(0, 5000)] def render(t, i): return create_grid(tos, i, 5, w, h) fmt = {'width': w, 'height': h, 'pix_fmt': 'yuv420p'} spec = vf.Spec(domain, render, fmt)\nspec.play(server) This plays this result (video is just a sample clip):","breadcrumbs":"Getting Started » Getting Started - DSL » Composition","id":"20","title":"Composition"},"21":{"body":"This notebook shows how to build custom filters to overlay data. This plays this result (video is just a sample clip):","breadcrumbs":"Getting Started » Getting Started - DSL » Viewing Telemetry (and User-Defined Filters)","id":"21","title":"Viewing Telemetry (and User-Defined Filters)"},"22":{"body":"vidformer builds on the data model introduced in the V2V paper . Frames are a single image. Frames are represented as their resolution and pixel format (the type and layout of pixels in memory, such as rgb24, gray8, or yuv420p). Videos are sequences of frames represented as an array. We index these arrays by rational numbers corresponding to their timestamp. Filters are functions which construct a frame. Filters can take inputs, such as frames or data. For example, DrawText may draw some text on a frame. Specs declarativly represent a video synthesis task. They represent the construction of a result videos, which is itself modeled as an array. Specs primairly contan domain and render functions. A spec's domain function returns the timestamps of the output frames. A spec's render function returns a composition of filters used to construct a frame at a spesific timestamp. Data Arrays allow using data in specs symbolically, as opposed to inserting constants directly into the spec. These allow for deduplication and loading large data blobs efficiently. Data Arrays can be backed by external data sources, such as SQL databases.","breadcrumbs":"Concepts & Data Model » Concepts & Data Model","id":"22","title":"Concepts & Data Model"},"23":{"body":"vidformer is a highly modular suite of tools that work together: vidformer-py : A Python 🐍 client for declarative video synthesis Provides an easy-to-use library for symbolically representing transformed videos Acts as a client for a VoD server (i.e., for yrden) Using vidformer-py is the best place to get started libvidformer : The core data-oriented declarative video editing library An embedded video processing execution engine with low-level interfaces Systems code, written in Rust 🦀 You should use if: You are building a VDBMS or other multimodal data-system infrastructure. You should not use if: You just want to use vidformer in your workflows or projects. yrden : A vidformer Video-on-Demand server Provides vidformer services over a REST-style API Allows for client libraries to be written in any language Serves video results via HLS streams Designed for local single-tenant use You should use if: You want to create faster video results in your workflows or projects. Note that yrden servers may be spun up transparently by client libraries, so you might use yrden without realizing it. igni : A planned scale-out Video-on-Demand server Will allow for scalable and secure public-facing VOD endpoints Client libraries in other languages: Writing a vidformer client library for other languages is simple. It's a few hundred lines of code, and you just have to construct some JSON. Contributions or suggestions for other languages are welcome. Other VoD servers: We provide yrden as a simple reference VoD server implementation. If you want to scale-out deployments, multi-tenant deployments, or deep integration with a specific system, writing another VoD server is needed. (In progress work)","breadcrumbs":"Tools » The vidformer Tools","id":"23","title":"The vidformer Tools"},"24":{"body":"PyPI version License vidformer-py is a Python 🐍 interface for vidformer . Our getting started guide explains how to use it. Quick links: 📦 PyPI 📘 Documentation - vidformer-py 📘 Documentation - vidformer.cv2 🧑‍💻 Source Code Publish: export FLIT_USERNAME='__token__' FLIT_PASSWORD=''\nflit publish","breadcrumbs":"Tools » vidformer-py » vidformer-py","id":"24","title":"vidformer-py"},"25":{"body":"Crates.io Version License (lib)vidformer is a core video synthesis/transformation library. It handles the movement, control flow, and processing of video and conventional (non-video) data. Quick links: 📦 Crates.io 📘 Documentation 🧑‍💻 Source Code","breadcrumbs":"Tools » libvidformer » vidformer - Video Data Transformation Library","id":"25","title":"vidformer - Video Data Transformation Library"},"26":{"body":"It's written in Rust 🦀 So it does some fancy parallel processing and does so safely Uses the FFmpeg libav libraries for multimedia stuff So it should work with nearly every video file ever made Uses Apache OpenDAL for I/O So it can access videos in a bunch of storage services Implements filters using OpenCV","breadcrumbs":"Tools » libvidformer » About","id":"26","title":"About"},"27":{"body":"This crate requires linking with FFmpeg, as detailed in the rusty_ffmpeg crate. We currently target FFmpeg 7.0.","breadcrumbs":"Tools » libvidformer » Building","id":"27","title":"Building"},"28":{"body":"For the vidformer builtin filters For the OpenCV/cv2 filters For using User Defined Filters (UDFs)","breadcrumbs":"Filters » Filters","id":"28","title":"Filters"},"29":{"body":"While most applications will use user-defined filters, vidformer ships with a handful of built-in filters to get you started:","breadcrumbs":"Filters » Built-in Filters » Built-in Filters","id":"29","title":"Built-in Filters"},"3":{"body":"🌐 Website 🚀 Getting Started 🐍 vidformer-py 🛠️ vidformer core","breadcrumbs":"Introduction » 📘 Documentation","id":"3","title":"📘 Documentation"},"30":{"body":"DrawText does exactly what it sounds like: draw text on a frame. For example: DrawText(frame, text=\"Hello, world!\", x=100, y=100, size=48, color=\"white\")","breadcrumbs":"Filters » Built-in Filters » DrawText","id":"30","title":"DrawText"},"31":{"body":"BoundingBox draws bounding boxes on a frame. For example: BoundingBox(frame, bounds=obj) Where obj is JSON with this schema: [ { \"class\": \"person\", \"confidence\": 0.916827917098999, \"x1\": 683.0721842447916, \"y1\": 100.92174338626751, \"x2\": 1006.863525390625, \"y2\": 720 }, { \"class\": \"dog\", \"confidence\": 0.902531921863556, \"x1\": 360.8750813802083, \"y1\": 47.983140622720974, \"x2\": 606.76171875, \"y2\": 717.9591837897462 }\n]","breadcrumbs":"Filters » Built-in Filters » BoundingBox","id":"31","title":"BoundingBox"},"32":{"body":"The Scale filter transforms one frame type to another. It changes both resolution and pixel format. This is the most important filter and is essential for building with vidformer. Arguments: Scale( frame: Frame, width: int = None, height: int = None, pix_fmt: str = None) By default missing width, height and format values are set to match frame. pix_fmt must match ffmpeg's name for a pixel format. For example: frame = Scale(frame, width=1280, height=720, pix_fmt=\"rgb24\")","breadcrumbs":"Filters » Built-in Filters » Scale","id":"32","title":"Scale"},"33":{"body":"IPC allows for calling User-Defined Filters (UDFs) running on the same system. It is an infrastructure-level filter and is used to implement other filters. It is configured with a socket and func, the filter's name, both strings. The IPC filter can not be directly invoked, rather IPC filters are constructed by a server upon request. This can be difficult, but vidformer-py handles this for you. As of right now IPC only supports rgb24 frames.","breadcrumbs":"Filters » Built-in Filters » IPC","id":"33","title":"IPC"},"34":{"body":"HStack & VStack allow for composing multiple frames together, stacking them either horizontally or vertically. It tries to automatically find a reasonable layout. Arguments: HStack( *frames: list[Frame], width: int, height: int, format: str) At least one frame is required, along with a width, height and format. For example: compilation = HStack(left_frame, right_frame, width=1280, height=720, format=\"rgb24\")","breadcrumbs":"Filters » Built-in Filters » HStack & VStack","id":"34","title":"HStack & VStack"},"35":{"body":"See vidformer.cv2 API docs . ⚠️ The cv2 module is a work in progress. If you find a bug or need a missing feature implemented feel free to file an issue or contribute yourself! Legend: ✅ - Support 🔸 - Support via OpenCV cv2 ❌ - Not yet implemented","breadcrumbs":"Filters » OpenCV/cv2 » OpenCV/cv2 Functions","id":"35","title":"OpenCV/cv2 Functions"},"36":{"body":"cv2.vidplay(video2) - Play a VideoWriter, Spec, or Source VideoWriter.spec() - Return the Spec of an output video Frame.numpy() - Return the frame as a numpy array cv2.setTo - The OpenCV Mat.setTo function (not in cv2)","breadcrumbs":"Filters » OpenCV/cv2 » Vidformer-specific Functions","id":"36","title":"Vidformer-specific Functions"},"37":{"body":"Class Status VideoCapture ✅ VideoWriter ✅ VideoWriter_fourcc ✅ Function Status imread ✅ imwrite ✅","breadcrumbs":"Filters » OpenCV/cv2 » opencv","id":"37","title":"opencv"},"38":{"body":"Drawing Functions: Function Status arrowedLine ✅ circle ✅ clipLine ❌ drawContours ❌ drawMarker ❌ ellipse ❌ ellipse2Poly ❌ fillConvexPoly ❌ fillPoly ❌ getFontScaleFromHeight 🔸 getTextSize 🔸 line ✅ polylines ❌ putText ✅ rectangle ✅","breadcrumbs":"Filters » OpenCV/cv2 » opencv.imgproc","id":"38","title":"opencv.imgproc"},"39":{"body":"Function Status addWeighted ✅","breadcrumbs":"Filters » OpenCV/cv2 » opencv.core","id":"39","title":"opencv.core"},"4":{"body":"Vidformer is a highly modular suite of tools that work together; these are detailed here . ❌ vidformer is NOT : A conventional video editor (like Premiere Pro or Final Cut) A video database/VDBMS A natural language query interface for video A computer vision library (like OpenCV) A computer vision AI model (like CLIP or Yolo) However, vidformer is highly complementary to each of these. If you're working on any of the later four, vidformer may be for you. File Layout : ./vidformer : The core transformation library ./vidformer-py : A Python video editing client ./vidformer-cli : A command-line interface for vidformer servers ./snake-pit : The main vidformer test suite ./docs : The vidformer website License: Vidformer is open source under Apache-2.0 . Contributions welcome.","breadcrumbs":"Introduction » 🔍 About the project","id":"4","title":"🔍 About the project"},"40":{"body":"To implement a new user-defined filter (UDF) you need to host a filter server over a UNIX Domain Socket. The vidformer-py library makes this easy. Filters take some combination of frames and data (string, int, bool) and return a single frame result. The vidformer project uses Python-style arguments, allowing ordered and named arguments (*args and **kwargs style). To do this we define a new filter class and host it: import vidformer as vf\nimport cv2 class MyFilter(vf.UDF): def filter(self, frame: vf.UDFFrame, name: str): \"\"\"Return the result frame.\"\"\" text = f\"Hello, {name}!\" image = frame.data().copy() cv2.putText( image, text, (100,100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 1, ) return vf.UDFFrame(image, frame.frame_type()) def filter_type(self, frame: vf.UDFFrameType, _name: str): \"\"\"Returns the type of the output frame.\"\"\" return frame mf_udf = MyFilter(\"MyFilter\") # name used for pretty printing my_filter = mf_udf.into_filter() # host the UDF in a subprocess, returns a vf.Filter Now we can use our newly-created filter in specs: my_filter(some_frame, \"vidformer\"). There is a catch, UDFs currently only support rgb24 pixel formats. So invoking my_filter will need to convert around this: scale = vf.Filter('Scale') def render(t, i): f = scale(tos[t], pix_fmt=\"rgb24\", width=1280, height=720) f = my_filter(f, \"world\") f = scale(f, pix_fmt=\"yuv420p\", width=1280, height=720) return f","breadcrumbs":"Filters » User-Defined Filters » User-Defined Filters","id":"40","title":"User-Defined Filters"},"41":{"body":"An unordered list of potential future features: Igni - A scale-out multi-tenant vidformer server in the cloud Supervision Integration Full GPU Acceleration WebAssembly Builds WebAssembly user defined filters & specs","breadcrumbs":"Roadmap » Roadmap","id":"41","title":"Roadmap"},"42":{"body":"","breadcrumbs":"FAQ » FAQ","id":"42","title":"FAQ"},"43":{"body":"In short, essentially everything. vidformer uses the FFmpeg/libav* libraries internally, so any media FFmpeg works with should work in vidformer as well. We support many container formats (e.g., mp4, mov) and codecs (e.g., H.264, VP8). A full list of supported codecs enabled in a vidformer build can be found by running: vidformer-cli codecs","breadcrumbs":"FAQ » What video formats does vidformer support?","id":"43","title":"What video formats does vidformer support?"},"44":{"body":"Yes, vidformer uses Apache OpenDAL for I/O, so most common data/storage access protocols are supported. However, not all storage services are enabled in distributed binaries. We guarantee that HTTP, S3, and the local filesystem always work.","breadcrumbs":"FAQ » Can I access remote videos on the internet?","id":"44","title":"Can I access remote videos on the internet?"},"45":{"body":"vidformer is far more expressive than the FFmpeg filter interface. Mainly, vidformer is designed for work around data, so edits are created programatically and edits can reference data. Also, vidformer enables serving resut videos on demand. vidformer uses the FFmpeg/libav* libraries internally, so any media FFmpeg works with should also work in vidformer.","breadcrumbs":"FAQ » How does vidformer compare to FFmpeg?","id":"45","title":"How does vidformer compare to FFmpeg?"},"46":{"body":"vidformer orchestrates data movment in video synthesis tasks, but does not implement image processing directly. Most use cases will still use OpenCV for this.","breadcrumbs":"FAQ » How does vidformer compare to OpenCV/cv2?","id":"46","title":"How does vidformer compare to OpenCV/cv2?"},"5":{"body":"Installation Getting started with the cv2 compatability layer Getting started with the core vidformer-py DSL","breadcrumbs":"Getting Started » Getting Started","id":"5","title":"Getting Started"},"6":{"body":"Using vidformer requires the Python client library, vidformer-py, and a yrden server which is distributed through vidformer-cli.","breadcrumbs":"Getting Started » Install » Install","id":"6","title":"Install"},"7":{"body":"pip install vidformer","breadcrumbs":"Getting Started » Install » vidformer-py","id":"7","title":"vidformer-py"},"8":{"body":"","breadcrumbs":"Getting Started » Install » vidformer-cli","id":"8","title":"vidformer-cli"},"9":{"body":"docker pull dominikwinecki/vidformer:latest\ndocker run --rm -it -p 8000:8000 dominikwinecki/vidformer:latest yrden --print-url This launches a vidformer yrden server, which is our reference server implementation for local usage, on port 8000. If you want to read or save video files locally add -v /my/local/dir:/data and then reference them as /data in the code. To use: import vidformer as vf\nserver = vf.YrdenServer(domain=\"localhost\", port=8000) # or for cv2\nimport vidformer.cv2 as cv2\ncv2.set_cv2_server(server)","breadcrumbs":"Getting Started » Install » 🐳 Docker:","id":"9","title":"🐳 Docker:"}},"length":47,"save":true},"fields":["title","body","breadcrumbs"],"index":{"body":{"root":{"0":{".":{"9":{"0":{"2":{"5":{"3":{"1":{"9":{"2":{"1":{"8":{"6":{"3":{"5":{"5":{"6":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"1":{"6":{"8":{"2":{"7":{"9":{"1":{"7":{"0":{"9":{"8":{"9":{"9":{"9":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":4,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}},"1":{"0":{"0":{",":{"1":{"0":{"0":{"df":1,"docs":{"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},".":{"9":{"2":{"1":{"7":{"4":{"3":{"3":{"8":{"6":{"2":{"6":{"7":{"5":{"1":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"6":{".":{"8":{"6":{"3":{"5":{"2":{"5":{"3":{"9":{"0":{"6":{"2":{"5":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":3,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}}},"8":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"2":{"8":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.0}}},"9":{"2":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":5,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}},"2":{".":{"0":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"4":{"df":2,"docs":{"18":{"tf":2.23606797749979},"20":{"tf":1.0}}},"5":{"5":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"3":{"0":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}},"6":{"0":{".":{"8":{"7":{"5":{"0":{"8":{"1":{"3":{"8":{"0":{"2":{"0":{"8":{"3":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"4":{"7":{".":{"9":{"8":{"3":{"1":{"4":{"0":{"6":{"2":{"2":{"7":{"2":{"0":{"9":{"7":{"4":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"5":{"0":{"0":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":2,"docs":{"18":{"tf":1.7320508075688772},"20":{"tf":1.0}},"x":{"5":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}},"6":{"0":{"6":{".":{"7":{"6":{"1":{"7":{"1":{"8":{"7":{"5":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"8":{"3":{".":{"0":{"7":{"2":{"1":{"8":{"4":{"2":{"4":{"4":{"7":{"9":{"1":{"6":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"7":{".":{"0":{"df":1,"docs":{"27":{"tf":1.0}}},"df":0,"docs":{}},"1":{"7":{".":{"9":{"5":{"9":{"1":{"8":{"3":{"7":{"8":{"9":{"7":{"4":{"6":{"2":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"2":{"0":{"df":2,"docs":{"18":{"tf":1.0},"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"8":{"0":{"0":{"0":{":":{"8":{"0":{"0":{"0":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.0}}},"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"40":{"tf":1.0}}}}},"df":0,"docs":{}}},"a":{"a":{"c":{"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}},"c":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"41":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}},"d":{"d":{"df":1,"docs":{"9":{"tf":1.0}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"39":{"tf":1.0}}}}}}}}},"df":1,"docs":{"12":{"tf":1.0}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"i":{"df":1,"docs":{"4":{"tf":1.0}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":7,"docs":{"1":{"tf":1.0},"2":{"tf":1.0},"22":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"33":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"34":{"tf":1.0}}}}},"w":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"44":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"d":{"6":{"4":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"23":{"tf":1.0},"32":{"tf":1.0}}}}}},"p":{"a":{"c":{"df":0,"docs":{},"h":{"df":3,"docs":{"26":{"tf":1.0},"4":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"35":{"tf":1.0}}},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"29":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"10":{"tf":1.0}}}},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"40":{"tf":1.0},"45":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"y":{"df":2,"docs":{"22":{"tf":2.23606797749979},"36":{"tf":1.0}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}}}}},"v":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":2,"docs":{"10":{"tf":1.0},"11":{"tf":1.0}}}}},"df":0,"docs":{}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.0}}}}},"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"10":{"tf":1.4142135623730951},"44":{"tf":1.0}}}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"b":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"40":{"tf":1.0}}}},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"32":{"tf":1.0},"33":{"tf":1.0}}}},"u":{"d":{"df":1,"docs":{"19":{"tf":1.0}}},"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"19":{"tf":1.0},"31":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"31":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"19":{"tf":1.0},"31":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}}},"s":{"=":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"o":{"b":{"df":0,"docs":{},"j":{"df":1,"docs":{"31":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"x":{"df":2,"docs":{"19":{"tf":1.4142135623730951},"31":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"k":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"u":{"df":0,"docs":{},"g":{"df":1,"docs":{"35":{"tf":1.0}}},"i":{"df":0,"docs":{},"l":{"d":{"df":8,"docs":{"11":{"tf":1.4142135623730951},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"27":{"tf":1.0},"32":{"tf":1.0},"41":{"tf":1.0},"43":{"tf":1.0}}},"df":0,"docs":{},"t":{"df":2,"docs":{"19":{"tf":1.0},"29":{"tf":1.4142135623730951}},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"28":{"tf":1.0}}}}}}},"n":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{}}}},"c":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"33":{"tf":1.0}}}},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"13":{"tf":1.0}}}},"df":0,"docs":{}},"p":{".":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"v":{"2":{".":{"c":{"a":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"p":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"o":{"df":1,"docs":{"11":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"18":{"tf":1.0},"46":{"tf":1.0}}}},"t":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"32":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}}},"i":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"l":{"df":1,"docs":{"38":{"tf":1.0}}}},"df":0,"docs":{}}},"l":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":3,"docs":{"31":{"tf":1.4142135623730951},"37":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"i":{"df":6,"docs":{"10":{"tf":2.449489742783178},"11":{"tf":1.0},"4":{"tf":1.0},"43":{"tf":1.0},"6":{"tf":1.0},"8":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"23":{"tf":2.449489742783178},"4":{"tf":1.0},"6":{"tf":1.0}}}}},"p":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":5,"docs":{"18":{"tf":1.0},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"21":{"tf":1.0},"4":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"o":{"df":0,"docs":{},"u":{"d":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"o":{"d":{"df":0,"docs":{},"e":{"c":{"df":1,"docs":{"43":{"tf":1.7320508075688772}}},"df":6,"docs":{"1":{"tf":1.0},"18":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":1.0},"25":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{},"l":{"a":{"b":{"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.7320508075688772},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}},"o":{"df":0,"docs":{},"r":{"=":{"\"":{"df":0,"docs":{},"w":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"30":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}},"s":{".":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"m":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"18":{"tf":1.0},"40":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"44":{"tf":1.0}}}}},"p":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"45":{"tf":1.0},"46":{"tf":1.0}}},"t":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":2,"docs":{"11":{"tf":1.0},"34":{"tf":1.0}}}},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}}}}},"o":{"df":0,"docs":{},"s":{"df":1,"docs":{"34":{"tf":1.0}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"20":{"tf":1.0},"22":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}}},"n":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"33":{"tf":1.0}}}}}}},"n":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.0},"22":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":4,"docs":{"18":{"tf":1.0},"22":{"tf":1.7320508075688772},"23":{"tf":1.0},"33":{"tf":1.0}}}},"df":0,"docs":{}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"43":{"tf":1.0}}}},"n":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"23":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"25":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"4":{"tf":1.0}}}},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"14":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"df":7,"docs":{"11":{"tf":1.0},"16":{"tf":1.0},"23":{"tf":1.0},"25":{"tf":1.0},"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}}}}}}}},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"27":{"tf":1.4142135623730951}},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":2,"docs":{"0":{"tf":1.0},"25":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":5,"docs":{"1":{"tf":1.0},"18":{"tf":2.23606797749979},"23":{"tf":1.0},"40":{"tf":1.0},"45":{"tf":1.0}},"e":{"_":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":1,"docs":{"14":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"27":{"tf":1.0},"40":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"21":{"tf":1.0}}}}}},"t":{"df":1,"docs":{"4":{"tf":1.0}}}},"v":{"2":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"40":{"tf":1.0}}}}}}}}}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}}}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":1,"docs":{"40":{"tf":1.0}}}}}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"v":{"2":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":1,"docs":{"9":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"36":{"tf":1.0}}}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":2,"docs":{"14":{"tf":1.0},"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"14":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"15":{"tf":1.0}}}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"c":{"(":{"*":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":0,"docs":{},"v":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"2":{"df":1,"docs":{"36":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":1.0},"15":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":10,"docs":{"1":{"tf":1.0},"12":{"tf":2.0},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"2":{"tf":2.0},"35":{"tf":1.4142135623730951},"36":{"tf":1.0},"40":{"tf":1.0},"5":{"tf":1.0},"9":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"44":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"b":{"a":{"df":0,"docs":{},"s":{"df":2,"docs":{"1":{"tf":1.0},"22":{"tf":1.0}},"e":{"/":{"df":0,"docs":{},"v":{"d":{"b":{"df":0,"docs":{},"m":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":11,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.0},"19":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":2.8284271247461903},"23":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"40":{"tf":1.0},"45":{"tf":1.4142135623730951},"46":{"tf":1.0},"9":{"tf":1.0}},"—":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"df":2,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"d":{"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}},"f":{"a":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"32":{"tf":1.0}}}}}},"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"40":{"tf":1.7320508075688772}},"i":{"df":0,"docs":{},"n":{"df":7,"docs":{"18":{"tf":1.0},"21":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.7320508075688772},"41":{"tf":1.0}}}}},"m":{"a":{"df":0,"docs":{},"n":{"d":{"df":4,"docs":{"1":{"tf":1.0},"15":{"tf":1.0},"23":{"tf":1.4142135623730951},"45":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"y":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.0},"45":{"tf":1.0}}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":4,"docs":{"11":{"tf":1.0},"2":{"tf":1.0},"27":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}},"v":{"df":1,"docs":{"10":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"33":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":3,"docs":{"22":{"tf":1.0},"33":{"tf":1.0},"46":{"tf":1.0}}}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":1.0},"15":{"tf":1.4142135623730951}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"15":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"44":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"o":{"c":{"df":2,"docs":{"35":{"tf":1.0},"4":{"tf":1.0}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"9":{"tf":1.7320508075688772}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"24":{"tf":1.4142135623730951},"25":{"tf":1.0},"3":{"tf":1.0}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}},"g":{"df":1,"docs":{"31":{"tf":1.0}}},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":5,"docs":{"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"i":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{":":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"r":{"a":{"df":0,"docs":{},"w":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}},"df":4,"docs":{"22":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0}},"m":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"38":{"tf":1.0}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"30":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"22":{"tf":1.0},"30":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"l":{"df":2,"docs":{"16":{"tf":1.4142135623730951},"5":{"tf":1.0}}}},"u":{"df":0,"docs":{},"e":{"df":1,"docs":{"13":{"tf":1.0}}}}},"df":0,"docs":{},"e":{".":{"df":0,"docs":{},"g":{"df":1,"docs":{"43":{"tf":1.4142135623730951}}}},"a":{"c":{"df":0,"docs":{},"h":{"df":3,"docs":{"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"4":{"tf":1.0}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"40":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"2":{"tf":1.0}}}}}}}},"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":4,"docs":{"1":{"tf":1.0},"23":{"tf":1.0},"4":{"tf":1.0},"45":{"tf":1.4142135623730951}},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"i":{"df":2,"docs":{"1":{"tf":1.0},"22":{"tf":1.0}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{"df":1,"docs":{"38":{"tf":1.0}},"e":{"2":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"m":{"b":{"df":0,"docs":{},"e":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"n":{"a":{"b":{"df":0,"docs":{},"l":{"df":4,"docs":{"1":{"tf":1.4142135623730951},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"d":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"32":{"tf":1.0},"43":{"tf":1.0}}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"43":{"tf":1.0}}}}}}}},"x":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"30":{"tf":1.0}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":9,"docs":{"10":{"tf":1.0},"14":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"22":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"24":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":2,"docs":{"10":{"tf":1.0},"24":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"45":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"f":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"a":{"c":{"df":0,"docs":{},"e":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{}},"q":{"df":1,"docs":{"42":{"tf":1.0}}},"r":{"df":1,"docs":{"45":{"tf":1.0}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"1":{"tf":1.0},"23":{"tf":1.0}}}}}}},"df":1,"docs":{"40":{"tf":2.0}},"e":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":2,"docs":{"35":{"tf":1.0},"41":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"35":{"tf":1.0}}}},"w":{"df":2,"docs":{"18":{"tf":1.0},"23":{"tf":1.0}}}},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"'":{"df":1,"docs":{"32":{"tf":1.0}}},"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"b":{"a":{"df":0,"docs":{},"v":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":5,"docs":{"11":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.4142135623730951},"43":{"tf":1.0},"45":{"tf":1.7320508075688772}}}}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":4,"docs":{"26":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.0},"9":{"tf":1.0}},"s":{"df":0,"docs":{},"y":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"44":{"tf":1.0}}}}}}}}},"l":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"'":{"df":1,"docs":{"33":{"tf":1.0}}},"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":13,"docs":{"12":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.4142135623730951},"22":{"tf":1.7320508075688772},"26":{"tf":1.0},"28":{"tf":2.0},"29":{"tf":1.7320508075688772},"32":{"tf":1.4142135623730951},"33":{"tf":2.23606797749979},"40":{"tf":2.449489742783178},"41":{"tf":1.0},"45":{"tf":1.0}}}}}},"n":{"a":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}},"df":1,"docs":{"4":{"tf":1.0}}}},"d":{"df":3,"docs":{"2":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"18":{"tf":1.0}}}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"d":{"=":{"'":{"<":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":1,"docs":{"24":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"=":{"'":{"_":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"_":{"_":{"df":1,"docs":{"24":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":1,"docs":{"24":{"tf":1.0}}}},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"25":{"tf":1.0}}}}},"m":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"o":{"c":{"df":0,"docs":{},"u":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"b":{"2":{"4":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}}},"df":7,"docs":{"1":{"tf":1.0},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"32":{"tf":1.7320508075688772},"34":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"p":{"df":4,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"1":{"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"5":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"20":{"tf":1.0}}}},"df":1,"docs":{"18":{"tf":1.7320508075688772}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{".":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"(":{")":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"36":{"tf":1.0}}}}}}}},"df":14,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":3.1622776601683795},"19":{"tf":1.0},"2":{"tf":1.0},"20":{"tf":1.7320508075688772},"22":{"tf":2.8284271247461903},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":2.23606797749979},"33":{"tf":1.0},"34":{"tf":1.7320508075688772},"36":{"tf":1.0},"40":{"tf":2.6457513110645907}},"r":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"35":{"tf":1.0}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":2,"docs":{"41":{"tf":1.0},"43":{"tf":1.0}}}},"n":{"c":{"df":1,"docs":{"33":{"tf":1.0}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":9,"docs":{"12":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"22":{"tf":2.0},"35":{"tf":1.0},"36":{"tf":1.4142135623730951},"37":{"tf":1.0},"38":{"tf":1.4142135623730951},"39":{"tf":1.0}}}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"41":{"tf":1.0}}}}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":6,"docs":{"12":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"2":{"tf":1.0},"24":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":1.7320508075688772}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"11":{"tf":1.0}}}},"p":{"df":0,"docs":{},"u":{"df":1,"docs":{"41":{"tf":1.0}}}},"r":{"a":{"df":0,"docs":{},"y":{"8":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"d":{".":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"h":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"*":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"u":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"44":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"d":{"df":4,"docs":{"13":{"tf":1.0},"17":{"tf":1.0},"2":{"tf":1.0},"24":{"tf":1.0}}},"df":0,"docs":{}}}},"h":{".":{"2":{"6":{"4":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"29":{"tf":1.0}},"l":{"df":2,"docs":{"25":{"tf":1.0},"33":{"tf":1.0}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"e":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":1,"docs":{"20":{"tf":1.7320508075688772}},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"=":{"7":{"2":{"0":{"df":4,"docs":{"20":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"/":{"/":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.0}}}}}}}}},"df":7,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"2":{"tf":1.4142135623730951},"20":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951}}}}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":4,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.0},"18":{"tf":1.0},"2":{"tf":1.0}}}},"p":{"df":1,"docs":{"18":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"'":{"df":1,"docs":{"14":{"tf":1.0}}},"df":3,"docs":{"11":{"tf":1.0},"18":{"tf":1.7320508075688772},"4":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.4142135623730951}}}}}}},"l":{"df":1,"docs":{"23":{"tf":1.0}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"34":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.7320508075688772}}}}},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"20":{"tf":1.0},"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"20":{"tf":1.4142135623730951},"34":{"tf":1.7320508075688772}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":1,"docs":{"44":{"tf":1.0}},"s":{":":{"/":{"/":{"df":0,"docs":{},"f":{".":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{".":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"d":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"2":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":2,"docs":{"14":{"tf":1.0},"18":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"u":{"b":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"/":{"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":0,"docs":{},"l":{"a":{"b":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"/":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"/":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"/":{"<":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{">":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"u":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}}}},"i":{".":{"df":2,"docs":{"18":{"tf":1.0},"23":{"tf":1.0}}},"/":{"df":0,"docs":{},"o":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}}}}},"m":{"a":{"df":0,"docs":{},"g":{"df":3,"docs":{"22":{"tf":1.0},"40":{"tf":1.4142135623730951},"46":{"tf":1.0}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":8,"docs":{"12":{"tf":1.0},"23":{"tf":1.0},"26":{"tf":1.0},"33":{"tf":1.0},"35":{"tf":1.4142135623730951},"40":{"tf":1.0},"46":{"tf":1.0},"9":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":9,"docs":{"10":{"tf":1.4142135623730951},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"2":{"tf":1.7320508075688772},"32":{"tf":1.0},"40":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"37":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"37":{"tf":1.0}}}}}}},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":3,"docs":{"18":{"tf":1.7320508075688772},"20":{"tf":1.4142135623730951},"22":{"tf":1.0}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}},"r":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":3,"docs":{"0":{"tf":1.0},"23":{"tf":1.0},"33":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"l":{"df":6,"docs":{"10":{"tf":1.0},"13":{"tf":1.4142135623730951},"17":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"n":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"a":{"d":{"df":2,"docs":{"15":{"tf":1.0},"18":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"t":{"(":{"c":{"a":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"v":{"2":{".":{"c":{"a":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}}}}},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":4,"docs":{"18":{"tf":1.0},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951},"40":{"tf":1.0}},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"18":{"tf":1.0}},"r":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"f":{"a":{"c":{"df":5,"docs":{"0":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"4":{"tf":1.4142135623730951},"45":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"n":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.0}}}}}}},"r":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"p":{"c":{"df":1,"docs":{"33":{"tf":2.23606797749979}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"35":{"tf":1.0}}}}},"t":{"'":{"df":3,"docs":{"18":{"tf":1.0},"23":{"tf":1.0},"26":{"tf":1.0}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":2,"docs":{"11":{"tf":1.0},"22":{"tf":1.0}}}}}}}},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"(":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":3,"docs":{"19":{"tf":1.0},"23":{"tf":1.0},"31":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951}}}}}}},"k":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}}}}},"df":0,"docs":{}}},"l":{"a":{"b":{"df":1,"docs":{"0":{"tf":1.0}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"u":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"23":{"tf":2.0},"4":{"tf":1.0}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"22":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"20":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"22":{"tf":1.0},"34":{"tf":1.0},"4":{"tf":1.0}}}}}},"z":{"df":0,"docs":{},"y":{"/":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"35":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"'":{"df":1,"docs":{"19":{"tf":1.0}}},"df":1,"docs":{"18":{"tf":1.4142135623730951}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"23":{"tf":1.0},"33":{"tf":1.0}}}}}},"i":{"b":{")":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"25":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"a":{"df":0,"docs":{},"v":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{},"f":{"d":{"df":0,"docs":{},"k":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"v":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}}}}},"r":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":9,"docs":{"11":{"tf":1.0},"23":{"tf":2.449489742783178},"25":{"tf":1.4142135623730951},"26":{"tf":1.0},"4":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":1.0},"45":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":4,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"4":{"tf":1.0}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":3,"docs":{"23":{"tf":1.0},"38":{"tf":1.0},"4":{"tf":1.0}}},"k":{"df":5,"docs":{"11":{"tf":1.0},"15":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"27":{"tf":1.0}}}},"s":{"df":0,"docs":{},"t":{"[":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"41":{"tf":1.0},"43":{"tf":1.0}}}}},"o":{"a":{"d":{"df":2,"docs":{"19":{"tf":1.4142135623730951},"22":{"tf":1.0}}},"df":0,"docs":{}},"c":{"a":{"df":0,"docs":{},"l":{"df":3,"docs":{"23":{"tf":1.0},"44":{"tf":1.0},"9":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.0}}}}},"m":{"a":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"45":{"tf":1.0}}}}}},"k":{"df":0,"docs":{},"e":{"df":1,"docs":{"40":{"tf":1.0}}}},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"43":{"tf":1.0}}}},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"18":{"tf":1.0}}}},"t":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"36":{"tf":1.0}}}}}}}},"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"18":{"tf":1.0},"32":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"i":{"a":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"d":{"=":{"\"":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"k":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"f":{"_":{"df":0,"docs":{},"u":{"d":{"df":0,"docs":{},"f":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"d":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"32":{"tf":1.0},"35":{"tf":1.0}}}}},"o":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"22":{"tf":1.7320508075688772},"4":{"tf":1.0}}}},"u":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}},"df":1,"docs":{"35":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":1,"docs":{"45":{"tf":1.0}}}},"v":{"df":1,"docs":{"43":{"tf":1.0}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"25":{"tf":1.0}}}}}}},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"46":{"tf":1.0}}}}}}}},"p":{"4":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}},"m":{"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"i":{"a":{"df":1,"docs":{"26":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}},"p":{"df":0,"docs":{},"l":{"df":2,"docs":{"18":{"tf":1.0},"34":{"tf":1.0}}}}}}}},"v":{"df":1,"docs":{"10":{"tf":1.0}}},"y":{"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"/":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{":":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"v":{"df":0,"docs":{},"f":{".":{"df":0,"docs":{},"u":{"d":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}}},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":4,"docs":{"18":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":2.0}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}},"e":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"d":{"df":4,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0},"35":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"13":{"tf":1.0}}}}}}},"w":{"df":1,"docs":{"40":{"tf":1.4142135623730951}},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"40":{"tf":1.0}}}}},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"25":{"tf":1.0}},"e":{"df":2,"docs":{"15":{"tf":1.0},"32":{"tf":1.7320508075688772}}}},"t":{"df":0,"docs":{},"e":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":3,"docs":{"15":{"tf":1.7320508075688772},"18":{"tf":1.0},"21":{"tf":1.0}}}}}},"df":2,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0}}}},"w":{"df":4,"docs":{"18":{"tf":2.0},"19":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.0}}}},"u":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"36":{"tf":1.0}}}}}}},"o":{"b":{"df":0,"docs":{},"j":{"df":1,"docs":{"31":{"tf":1.0}},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":1,"docs":{"14":{"tf":1.0}},"n":{"df":2,"docs":{"32":{"tf":1.0},"34":{"tf":1.0}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"v":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"39":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"g":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"c":{"df":1,"docs":{"38":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"/":{"c":{"df":0,"docs":{},"v":{"2":{"df":3,"docs":{"28":{"tf":1.0},"35":{"tf":1.0},"46":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":9,"docs":{"11":{"tf":1.0},"12":{"tf":1.0},"2":{"tf":1.0},"26":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.0},"4":{"tf":1.0},"46":{"tf":1.0}}}},"d":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}},"df":4,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"2":{"tf":1.0},"4":{"tf":1.0}}}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":1,"docs":{"22":{"tf":1.0}}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.7320508075688772}}}}}},"r":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":1,"docs":{"46":{"tf":1.0}}}}}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"18":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"0":{"tf":1.0}}}},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"14":{"tf":1.0}}},"t":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":5,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"23":{"tf":1.4142135623730951},"41":{"tf":1.0}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":5,"docs":{"18":{"tf":2.0},"19":{"tf":1.0},"22":{"tf":1.0},"36":{"tf":1.0},"40":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"19":{"tf":1.0},"20":{"tf":1.0},"23":{"tf":1.0},"40":{"tf":1.0}},"l":{"a":{"df":0,"docs":{},"y":{"df":2,"docs":{"19":{"tf":1.0},"21":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":1,"docs":{"12":{"tf":1.0}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}}},"r":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"15":{"tf":1.0}}}}},"df":1,"docs":{"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"31":{"tf":1.0}}}}}}},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"7":{"tf":1.0}},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"t":{"df":1,"docs":{"4":{"tf":1.0}}},"x":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"b":{"2":{"4":{"df":2,"docs":{"32":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":3,"docs":{"18":{"tf":1.0},"20":{"tf":1.0},"32":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":3,"docs":{"22":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}}},"l":{"a":{"c":{"df":0,"docs":{},"e":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"23":{"tf":1.0}}}},"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}},"y":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":6,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":2.6457513110645907},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"36":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"r":{"df":0,"docs":{},"t":{"=":{"8":{"0":{"0":{"0":{"df":2,"docs":{"18":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"41":{"tf":1.0}}}}}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":2,"docs":{"1":{"tf":1.0},"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"40":{"tf":1.0}}}}}},"i":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}}},"df":3,"docs":{"18":{"tf":1.4142135623730951},"40":{"tf":1.0},"9":{"tf":1.0}}}}},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":5,"docs":{"1":{"tf":1.0},"23":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"46":{"tf":1.0}}}}}},"df":1,"docs":{"4":{"tf":1.0}},"g":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"45":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":3,"docs":{"12":{"tf":1.0},"23":{"tf":1.0},"35":{"tf":1.0}}}}}}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":4,"docs":{"0":{"tf":1.0},"23":{"tf":1.4142135623730951},"4":{"tf":1.0},"40":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"44":{"tf":1.0}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"0":{"tf":1.0},"23":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":1,"docs":{"24":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"9":{"tf":1.0}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}},"y":{"df":10,"docs":{"16":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":1.7320508075688772},"3":{"tf":1.0},"33":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"0":{"tf":1.0},"24":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":6,"docs":{"2":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"1":{"tf":1.0},"4":{"tf":1.0}}}}},"i":{"c":{"df":0,"docs":{},"k":{"df":3,"docs":{"2":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0}}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"(":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"2":{"4":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.0}}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"22":{"tf":1.0}}}}}}},"df":1,"docs":{"19":{"tf":1.0}},"e":{"a":{"d":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":1,"docs":{"23":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"34":{"tf":1.0}}}}}},"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"18":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":1,"docs":{"38":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":3,"docs":{"23":{"tf":1.0},"45":{"tf":1.0},"9":{"tf":1.4142135623730951}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"l":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.0}}}}},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"40":{"tf":1.0}}}},"df":5,"docs":{"15":{"tf":1.0},"18":{"tf":2.0},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"l":{"a":{"c":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":1,"docs":{"11":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":3,"docs":{"1":{"tf":1.0},"22":{"tf":2.0},"23":{"tf":1.0}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"33":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"r":{"df":4,"docs":{"11":{"tf":1.0},"27":{"tf":1.0},"34":{"tf":1.0},"6":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"22":{"tf":1.0},"32":{"tf":1.0}}}}}},"t":{"df":1,"docs":{"23":{"tf":1.0}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":10,"docs":{"1":{"tf":1.4142135623730951},"13":{"tf":1.0},"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}}},"t":{"df":1,"docs":{"45":{"tf":1.0}}}}},"t":{"df":3,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"1":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":7,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"22":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"40":{"tf":2.6457513110645907}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"g":{"b":{"2":{"4":{"df":3,"docs":{"22":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"20":{"tf":1.0},"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":1,"docs":{"33":{"tf":1.0}}}}}},"m":{"df":1,"docs":{"9":{"tf":1.0}}},"o":{"a":{"d":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"p":{"df":1,"docs":{"41":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"u":{"df":0,"docs":{},"n":{"df":4,"docs":{"15":{"tf":1.0},"33":{"tf":1.0},"43":{"tf":1.0},"9":{"tf":1.0}}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.0},"26":{"tf":1.0}},"y":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"27":{"tf":1.0}}}}}}}}},"df":0,"docs":{}}}}}},"s":{"3":{"df":1,"docs":{"44":{"tf":1.0}}},"a":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":1,"docs":{"26":{"tf":1.0}}}},"m":{"df":0,"docs":{},"e":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"33":{"tf":1.0}}},"p":{"df":0,"docs":{},"l":{"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"e":{"df":4,"docs":{"13":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"9":{"tf":1.0}}}}},"c":{"a":{"df":0,"docs":{},"l":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"32":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"[":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}}},"df":4,"docs":{"23":{"tf":1.4142135623730951},"32":{"tf":1.7320508075688772},"40":{"tf":1.0},"41":{"tf":1.0}}}}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"a":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"2":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":4,"docs":{"12":{"tf":1.0},"13":{"tf":1.0},"17":{"tf":1.0},"35":{"tf":1.0}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}}}},"r":{"df":0,"docs":{},"v":{"df":2,"docs":{"23":{"tf":1.0},"45":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":9,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.7320508075688772},"23":{"tf":2.6457513110645907},"33":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":1.7320508075688772}}}},"i":{"c":{"df":3,"docs":{"23":{"tf":1.0},"26":{"tf":1.0},"44":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"32":{"tf":1.0}}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"29":{"tf":1.0}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"43":{"tf":1.0}}}},"w":{"df":1,"docs":{"21":{"tf":1.0}}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"22":{"tf":1.0},"23":{"tf":1.0},"40":{"tf":1.0}}}}},"z":{"df":0,"docs":{},"e":{"=":{"4":{"8":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"k":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"15":{"tf":1.0}}}}},"n":{"a":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"r":{"c":{"df":7,"docs":{"11":{"tf":1.0},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"36":{"tf":1.0},"4":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"'":{"df":1,"docs":{"22":{"tf":1.4142135623730951}}},".":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":7,"docs":{"18":{"tf":1.7320508075688772},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":2.0},"36":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0}},"i":{"df":0,"docs":{},"f":{"df":3,"docs":{"1":{"tf":1.7320508075688772},"23":{"tf":1.0},"36":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}}}},"q":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{},"n":{"d":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"t":{"df":10,"docs":{"12":{"tf":1.4142135623730951},"15":{"tf":1.0},"16":{"tf":1.4142135623730951},"18":{"tf":1.7320508075688772},"2":{"tf":1.7320508075688772},"23":{"tf":1.0},"24":{"tf":1.0},"29":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":1.7320508075688772}}}},"t":{"df":0,"docs":{},"u":{"df":3,"docs":{"37":{"tf":1.4142135623730951},"38":{"tf":1.0},"39":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"46":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{}}},"r":{"df":3,"docs":{"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}},"e":{"a":{"df":0,"docs":{},"m":{"/":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"13":{"tf":1.0}}}},"df":0,"docs":{}}}},"=":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"23":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"26":{"tf":1.0}}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":2,"docs":{"23":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}}},"u":{"b":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}}}}},"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"22":{"tf":1.7320508075688772}}}},"d":{"df":0,"docs":{},"o":{"df":1,"docs":{"10":{"tf":1.7320508075688772}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.4142135623730951}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":1,"docs":{"41":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":5,"docs":{"33":{"tf":1.0},"35":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":1.7320508075688772},"44":{"tf":1.0}}}}}}}},"y":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":2,"docs":{"22":{"tf":1.0},"23":{"tf":1.0}}}}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":3,"docs":{"22":{"tf":1.0},"23":{"tf":1.0},"46":{"tf":1.0}},"s":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"25":{"tf":1.0}}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":3,"docs":{"0":{"tf":1.0},"23":{"tf":1.7320508075688772},"33":{"tf":1.0}}}}}}}},"t":{"a":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":3,"docs":{"18":{"tf":1.0},"22":{"tf":1.0},"40":{"tf":1.0}}}},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"27":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"k":{"df":2,"docs":{"22":{"tf":1.0},"46":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"21":{"tf":1.0}}}}}}}}},"n":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"41":{"tf":1.0}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}},"x":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"30":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":3,"docs":{"22":{"tf":1.0},"30":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"20":{"tf":1.0}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":1,"docs":{"6":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":3,"docs":{"18":{"tf":1.7320508075688772},"19":{"tf":1.0},"22":{"tf":1.7320508075688772}}}}},"df":0,"docs":{}}}}}},"o":{"df":1,"docs":{"18":{"tf":1.0}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"23":{"tf":1.0},"34":{"tf":1.0},"4":{"tf":1.0}}}}}},"o":{"df":0,"docs":{},"l":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"4":{"tf":1.0}}}},"s":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.4142135623730951},"19":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"[":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.0},"19":{"tf":1.0}}}},"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":6,"docs":{"0":{"tf":1.0},"1":{"tf":1.4142135623730951},"23":{"tf":1.0},"25":{"tf":1.0},"32":{"tf":1.0},"4":{"tf":1.0}}}}}},"p":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"1":{"tf":1.0},"23":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":1,"docs":{"1":{"tf":1.0}}}}}}}},"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"34":{"tf":1.0}}},"u":{"df":0,"docs":{},"e":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"y":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":3,"docs":{"22":{"tf":1.0},"32":{"tf":1.0},"40":{"tf":1.0}}}}}},"u":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"2":{"2":{".":{"0":{"4":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"d":{"df":0,"docs":{},"f":{"df":3,"docs":{"28":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.7320508075688772}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":1,"docs":{"40":{"tf":1.0}}}},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":1,"docs":{"23":{"tf":1.0}},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"33":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"l":{"df":1,"docs":{"9":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"b":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"(":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{":":{"/":{"/":{"df":0,"docs":{},"f":{".":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{".":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"d":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"2":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":1,"docs":{"19":{"tf":1.0}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"s":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":20,"docs":{"1":{"tf":1.0},"10":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":2.23606797749979},"2":{"tf":1.0},"22":{"tf":1.4142135623730951},"23":{"tf":2.8284271247461903},"24":{"tf":1.0},"26":{"tf":1.7320508075688772},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.7320508075688772},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.4142135623730951},"6":{"tf":1.0},"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":6,"docs":{"21":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.0}}}},"r":{"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"/":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"v":{"2":{"df":0,"docs":{},"v":{"df":1,"docs":{"22":{"tf":1.0}}}},"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":1,"docs":{"32":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"b":{"df":0,"docs":{},"m":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":3,"docs":{"0":{"tf":1.4142135623730951},"24":{"tf":1.0},"25":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}}}}},"f":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"df":1,"docs":{"19":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"h":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"'":{"df":0,"docs":{},"s":{"c":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"(":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"u":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"40":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"y":{"df":0,"docs":{},"r":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":1,"docs":{"10":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"\"":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"\"":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"'":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}}}},"df":4,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.0},"40":{"tf":1.0},"9":{"tf":1.0}},"r":{"df":1,"docs":{"18":{"tf":1.0}}}},"i":{"a":{"df":2,"docs":{"23":{"tf":1.0},"35":{"tf":1.0}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"'":{"df":1,"docs":{"18":{"tf":1.0}}},"c":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"37":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":19,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":2.0},"14":{"tf":1.0},"15":{"tf":2.0},"18":{"tf":3.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.7320508075688772},"23":{"tf":2.8284271247461903},"25":{"tf":2.0},"26":{"tf":1.4142135623730951},"36":{"tf":1.0},"4":{"tf":2.0},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.0},"9":{"tf":1.0}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"36":{"tf":1.0},"37":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":1,"docs":{"36":{"tf":1.0}}},"df":0,"docs":{}}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"c":{"df":1,"docs":{"37":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":30,"docs":{"0":{"tf":1.0},"1":{"tf":2.0},"10":{"tf":2.0},"11":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":1.0},"16":{"tf":1.0},"18":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":2.8284271247461903},"24":{"tf":2.0},"25":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"3":{"tf":1.4142135623730951},"32":{"tf":1.0},"33":{"tf":1.0},"36":{"tf":1.0},"4":{"tf":3.3166247903554},"40":{"tf":2.0},"41":{"tf":1.0},"43":{"tf":2.23606797749979},"44":{"tf":1.0},"45":{"tf":2.449489742783178},"46":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951},"8":{"tf":1.0},"9":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"r":{"'":{"df":1,"docs":{"2":{"tf":1.0}}},".":{"c":{"df":0,"docs":{},"v":{"2":{"df":6,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.0},"2":{"tf":1.4142135623730951},"24":{"tf":1.0},"35":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"_":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"'":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.0}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"o":{"d":{"df":1,"docs":{"23":{"tf":2.23606797749979}}},"df":0,"docs":{}},"p":{"8":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":1,"docs":{"18":{"tf":1.0}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"*":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":2,"docs":{"20":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"w":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"k":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":2,"docs":{"12":{"tf":1.0},"16":{"tf":1.0}}}}}}}}}}},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"18":{"tf":1.0},"23":{"tf":1.7320508075688772},"9":{"tf":1.0}}}},"y":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":1,"docs":{"20":{"tf":1.7320508075688772}},"e":{"b":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"41":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"3":{"tf":1.0},"4":{"tf":1.0}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"l":{"df":2,"docs":{"18":{"tf":1.0},"43":{"tf":1.0}}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"10":{"tf":1.0}}}}},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"=":{"1":{"2":{"8":{"0":{"df":4,"docs":{"20":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}}},"df":7,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"2":{"tf":1.4142135623730951},"20":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.0}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"k":{"df":11,"docs":{"12":{"tf":1.0},"13":{"tf":1.4142135623730951},"15":{"tf":1.0},"18":{"tf":1.7320508075688772},"23":{"tf":1.4142135623730951},"26":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.4142135623730951},"43":{"tf":1.4142135623730951},"44":{"tf":1.0},"45":{"tf":1.7320508075688772}},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}}}},"l":{"d":{"df":6,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.0},"18":{"tf":1.0},"2":{"tf":1.0},"30":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"15":{"tf":1.0},"23":{"tf":1.4142135623730951}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"26":{"tf":1.0}}}}}}}}},"x":{"1":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"2":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"=":{"1":{"0":{"0":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"10":{"tf":1.0}}},"y":{"1":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"2":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"=":{"1":{"0":{"0":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"10":{"tf":1.0}},"e":{"df":1,"docs":{"44":{"tf":1.0}}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"4":{"tf":1.0}}}},"u":{"'":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"35":{"tf":1.0}}}}}}}}},"r":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":3,"docs":{"23":{"tf":2.23606797749979},"6":{"tf":1.0},"9":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":3,"docs":{"18":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"breadcrumbs":{"root":{"0":{".":{"9":{"0":{"2":{"5":{"3":{"1":{"9":{"2":{"1":{"8":{"6":{"3":{"5":{"5":{"6":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"1":{"6":{"8":{"2":{"7":{"9":{"1":{"7":{"0":{"9":{"8":{"9":{"9":{"9":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":4,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}},"1":{"0":{"0":{",":{"1":{"0":{"0":{"df":1,"docs":{"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},".":{"9":{"2":{"1":{"7":{"4":{"3":{"3":{"8":{"6":{"2":{"6":{"7":{"5":{"1":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"6":{".":{"8":{"6":{"3":{"5":{"2":{"5":{"3":{"9":{"0":{"6":{"2":{"5":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":3,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}}},"8":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"2":{"8":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.0}}},"9":{"2":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":5,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}},"2":{".":{"0":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"4":{"df":2,"docs":{"18":{"tf":2.23606797749979},"20":{"tf":1.0}}},"5":{"5":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"3":{"0":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}},"6":{"0":{".":{"8":{"7":{"5":{"0":{"8":{"1":{"3":{"8":{"0":{"2":{"0":{"8":{"3":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"4":{"7":{".":{"9":{"8":{"3":{"1":{"4":{"0":{"6":{"2":{"2":{"7":{"2":{"0":{"9":{"7":{"4":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"5":{"0":{"0":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":2,"docs":{"18":{"tf":1.7320508075688772},"20":{"tf":1.0}},"x":{"5":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}},"6":{"0":{"6":{".":{"7":{"6":{"1":{"7":{"1":{"8":{"7":{"5":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"8":{"3":{".":{"0":{"7":{"2":{"1":{"8":{"4":{"2":{"4":{"4":{"7":{"9":{"1":{"6":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"7":{".":{"0":{"df":1,"docs":{"27":{"tf":1.0}}},"df":0,"docs":{}},"1":{"7":{".":{"9":{"5":{"9":{"1":{"8":{"3":{"7":{"8":{"9":{"7":{"4":{"6":{"2":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"2":{"0":{"df":2,"docs":{"18":{"tf":1.0},"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"8":{"0":{"0":{"0":{":":{"8":{"0":{"0":{"0":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.0}}},"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"40":{"tf":1.0}}}}},"df":0,"docs":{}}},"a":{"a":{"c":{"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}},"c":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"41":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.7320508075688772}}}}}},"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}},"d":{"d":{"df":1,"docs":{"9":{"tf":1.0}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"39":{"tf":1.0}}}}}}}}},"df":1,"docs":{"12":{"tf":1.0}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"i":{"df":1,"docs":{"4":{"tf":1.0}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":7,"docs":{"1":{"tf":1.0},"2":{"tf":1.0},"22":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"33":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"34":{"tf":1.0}}}}},"w":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"44":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"d":{"6":{"4":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"23":{"tf":1.0},"32":{"tf":1.0}}}}}},"p":{"a":{"c":{"df":0,"docs":{},"h":{"df":3,"docs":{"26":{"tf":1.0},"4":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"35":{"tf":1.0}}},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"29":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"10":{"tf":1.0}}}},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"40":{"tf":1.0},"45":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"y":{"df":2,"docs":{"22":{"tf":2.23606797749979},"36":{"tf":1.0}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}}}}},"v":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":2,"docs":{"10":{"tf":1.0},"11":{"tf":1.0}}}}},"df":0,"docs":{}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.0}}}}},"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"10":{"tf":1.7320508075688772},"44":{"tf":1.0}}}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"b":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"40":{"tf":1.0}}}},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"32":{"tf":1.0},"33":{"tf":1.0}}}},"u":{"d":{"df":1,"docs":{"19":{"tf":1.0}}},"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"19":{"tf":1.4142135623730951},"31":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"31":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"19":{"tf":1.0},"31":{"tf":1.7320508075688772}}}}},"df":0,"docs":{}}}},"s":{"=":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"o":{"b":{"df":0,"docs":{},"j":{"df":1,"docs":{"31":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"x":{"df":2,"docs":{"19":{"tf":1.7320508075688772},"31":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"k":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"u":{"df":0,"docs":{},"g":{"df":1,"docs":{"35":{"tf":1.0}}},"i":{"df":0,"docs":{},"l":{"d":{"df":8,"docs":{"11":{"tf":1.7320508075688772},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"27":{"tf":1.4142135623730951},"32":{"tf":1.0},"41":{"tf":1.0},"43":{"tf":1.0}}},"df":0,"docs":{},"t":{"df":7,"docs":{"19":{"tf":1.0},"29":{"tf":2.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0},"34":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"28":{"tf":1.0}}}}}}},"n":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{}}}},"c":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"33":{"tf":1.0}}}},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"13":{"tf":1.0}}}},"df":0,"docs":{}},"p":{".":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"v":{"2":{".":{"c":{"a":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"p":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"o":{"df":1,"docs":{"11":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"18":{"tf":1.0},"46":{"tf":1.0}}}},"t":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"32":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}}},"i":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"l":{"df":1,"docs":{"38":{"tf":1.0}}}},"df":0,"docs":{}}},"l":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":3,"docs":{"31":{"tf":1.4142135623730951},"37":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"i":{"df":6,"docs":{"10":{"tf":2.449489742783178},"11":{"tf":1.0},"4":{"tf":1.0},"43":{"tf":1.0},"6":{"tf":1.0},"8":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"23":{"tf":2.449489742783178},"4":{"tf":1.0},"6":{"tf":1.0}}}}},"p":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":5,"docs":{"18":{"tf":1.0},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"21":{"tf":1.0},"4":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"o":{"df":0,"docs":{},"u":{"d":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"o":{"d":{"df":0,"docs":{},"e":{"c":{"df":1,"docs":{"43":{"tf":1.7320508075688772}}},"df":6,"docs":{"1":{"tf":1.0},"18":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":1.0},"25":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{},"l":{"a":{"b":{"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.7320508075688772},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}},"o":{"df":0,"docs":{},"r":{"=":{"\"":{"df":0,"docs":{},"w":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"30":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}},"s":{".":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"m":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"18":{"tf":1.0},"40":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"44":{"tf":1.0}}}}},"p":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"45":{"tf":1.4142135623730951},"46":{"tf":1.4142135623730951}}},"t":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":2,"docs":{"11":{"tf":1.0},"34":{"tf":1.0}}}},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}}}}},"o":{"df":0,"docs":{},"s":{"df":1,"docs":{"34":{"tf":1.0}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"22":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}}},"n":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.7320508075688772}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"33":{"tf":1.0}}}}}}},"n":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.0},"22":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":4,"docs":{"18":{"tf":1.0},"22":{"tf":1.7320508075688772},"23":{"tf":1.0},"33":{"tf":1.0}}}},"df":0,"docs":{}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"43":{"tf":1.0}}}},"n":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"23":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"25":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"4":{"tf":1.0}}}},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"14":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"df":7,"docs":{"11":{"tf":1.0},"16":{"tf":1.0},"23":{"tf":1.0},"25":{"tf":1.0},"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}}}}}}}},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"27":{"tf":1.4142135623730951}},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":2,"docs":{"0":{"tf":1.0},"25":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":5,"docs":{"1":{"tf":1.0},"18":{"tf":2.23606797749979},"23":{"tf":1.0},"40":{"tf":1.0},"45":{"tf":1.0}},"e":{"_":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":1,"docs":{"14":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"27":{"tf":1.0},"40":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"21":{"tf":1.0}}}}}},"t":{"df":1,"docs":{"4":{"tf":1.0}}}},"v":{"2":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"40":{"tf":1.0}}}}}}}}}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}}}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":1,"docs":{"40":{"tf":1.0}}}}}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"v":{"2":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":1,"docs":{"9":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"36":{"tf":1.0}}}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":2,"docs":{"14":{"tf":1.0},"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"14":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"15":{"tf":1.0}}}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"c":{"(":{"*":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":0,"docs":{},"v":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"2":{"df":1,"docs":{"36":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":1.0},"15":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":11,"docs":{"1":{"tf":1.0},"12":{"tf":2.449489742783178},"13":{"tf":1.0},"14":{"tf":2.0},"15":{"tf":1.4142135623730951},"2":{"tf":2.0},"35":{"tf":1.4142135623730951},"36":{"tf":1.0},"40":{"tf":1.0},"5":{"tf":1.0},"9":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"44":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"b":{"a":{"df":0,"docs":{},"s":{"df":2,"docs":{"1":{"tf":1.0},"22":{"tf":1.0}},"e":{"/":{"df":0,"docs":{},"v":{"d":{"b":{"df":0,"docs":{},"m":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":11,"docs":{"0":{"tf":1.7320508075688772},"1":{"tf":1.0},"19":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":3.1622776601683795},"23":{"tf":1.4142135623730951},"25":{"tf":1.7320508075688772},"40":{"tf":1.0},"45":{"tf":1.4142135623730951},"46":{"tf":1.0},"9":{"tf":1.0}},"—":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"df":2,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"d":{"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}},"f":{"a":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"32":{"tf":1.0}}}}}},"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"40":{"tf":1.7320508075688772}},"i":{"df":0,"docs":{},"n":{"df":7,"docs":{"18":{"tf":1.0},"21":{"tf":1.4142135623730951},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":2.23606797749979},"41":{"tf":1.0}}}}},"m":{"a":{"df":0,"docs":{},"n":{"d":{"df":4,"docs":{"1":{"tf":1.0},"15":{"tf":1.0},"23":{"tf":1.4142135623730951},"45":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"y":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.0},"45":{"tf":1.0}}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":4,"docs":{"11":{"tf":1.0},"2":{"tf":1.0},"27":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}},"v":{"df":1,"docs":{"10":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"33":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":3,"docs":{"22":{"tf":1.0},"33":{"tf":1.0},"46":{"tf":1.0}}}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":1.0},"15":{"tf":1.4142135623730951}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"15":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"44":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"o":{"c":{"df":2,"docs":{"35":{"tf":1.0},"4":{"tf":1.0}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"9":{"tf":2.0}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"24":{"tf":1.4142135623730951},"25":{"tf":1.0},"3":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}},"g":{"df":1,"docs":{"31":{"tf":1.0}}},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":5,"docs":{"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"i":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{":":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"r":{"a":{"df":0,"docs":{},"w":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}},"df":4,"docs":{"22":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0}},"m":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"38":{"tf":1.0}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"30":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"22":{"tf":1.0},"30":{"tf":1.7320508075688772}}}}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"l":{"df":7,"docs":{"16":{"tf":2.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"5":{"tf":1.0}}}},"u":{"df":0,"docs":{},"e":{"df":1,"docs":{"13":{"tf":1.0}}}}},"df":0,"docs":{},"e":{".":{"df":0,"docs":{},"g":{"df":1,"docs":{"43":{"tf":1.4142135623730951}}}},"a":{"c":{"df":0,"docs":{},"h":{"df":3,"docs":{"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"4":{"tf":1.0}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"40":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"2":{"tf":1.0}}}}}}}},"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":4,"docs":{"1":{"tf":1.0},"23":{"tf":1.0},"4":{"tf":1.0},"45":{"tf":1.4142135623730951}},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"i":{"df":2,"docs":{"1":{"tf":1.0},"22":{"tf":1.0}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{"df":1,"docs":{"38":{"tf":1.0}},"e":{"2":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"m":{"b":{"df":0,"docs":{},"e":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"n":{"a":{"b":{"df":0,"docs":{},"l":{"df":4,"docs":{"1":{"tf":1.4142135623730951},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"d":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"32":{"tf":1.0},"43":{"tf":1.0}}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"43":{"tf":1.0}}}}}}}},"x":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"30":{"tf":1.0}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":9,"docs":{"10":{"tf":1.0},"14":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"22":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"24":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":2,"docs":{"10":{"tf":1.0},"24":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"45":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"f":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"a":{"c":{"df":0,"docs":{},"e":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{}},"q":{"df":5,"docs":{"42":{"tf":1.7320508075688772},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.0}}},"r":{"df":1,"docs":{"45":{"tf":1.0}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"1":{"tf":1.0},"23":{"tf":1.0}}}}}}},"df":1,"docs":{"40":{"tf":2.0}},"e":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":2,"docs":{"35":{"tf":1.0},"41":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"35":{"tf":1.0}}}},"w":{"df":2,"docs":{"18":{"tf":1.0},"23":{"tf":1.0}}}},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"'":{"df":1,"docs":{"32":{"tf":1.0}}},"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"b":{"a":{"df":0,"docs":{},"v":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":5,"docs":{"11":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.4142135623730951},"43":{"tf":1.0},"45":{"tf":2.0}}}}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":4,"docs":{"26":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.0},"9":{"tf":1.0}},"s":{"df":0,"docs":{},"y":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"44":{"tf":1.0}}}}}}}}},"l":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"'":{"df":1,"docs":{"33":{"tf":1.0}}},"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":21,"docs":{"12":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.7320508075688772},"22":{"tf":1.7320508075688772},"26":{"tf":1.0},"28":{"tf":2.449489742783178},"29":{"tf":2.449489742783178},"30":{"tf":1.4142135623730951},"31":{"tf":1.4142135623730951},"32":{"tf":2.0},"33":{"tf":2.6457513110645907},"34":{"tf":1.4142135623730951},"35":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.0},"38":{"tf":1.0},"39":{"tf":1.0},"40":{"tf":3.0},"41":{"tf":1.0},"45":{"tf":1.0}}}}}},"n":{"a":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}},"df":1,"docs":{"4":{"tf":1.0}}}},"d":{"df":3,"docs":{"2":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"18":{"tf":1.0}}}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"d":{"=":{"'":{"<":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":1,"docs":{"24":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"=":{"'":{"_":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"_":{"_":{"df":1,"docs":{"24":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":1,"docs":{"24":{"tf":1.0}}}},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"25":{"tf":1.0}}}}},"m":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"o":{"c":{"df":0,"docs":{},"u":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"b":{"2":{"4":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}}},"df":7,"docs":{"1":{"tf":1.0},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"32":{"tf":1.7320508075688772},"34":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":1.7320508075688772}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"p":{"df":4,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"1":{"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"5":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"20":{"tf":1.0}}}},"df":1,"docs":{"18":{"tf":1.7320508075688772}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{".":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"(":{")":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"36":{"tf":1.0}}}}}}}},"df":14,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":3.1622776601683795},"19":{"tf":1.0},"2":{"tf":1.0},"20":{"tf":1.7320508075688772},"22":{"tf":2.8284271247461903},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":2.23606797749979},"33":{"tf":1.0},"34":{"tf":1.7320508075688772},"36":{"tf":1.0},"40":{"tf":2.6457513110645907}},"r":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"35":{"tf":1.0}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":2,"docs":{"41":{"tf":1.0},"43":{"tf":1.0}}}},"n":{"c":{"df":1,"docs":{"33":{"tf":1.0}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":9,"docs":{"12":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"22":{"tf":2.0},"35":{"tf":1.4142135623730951},"36":{"tf":1.7320508075688772},"37":{"tf":1.0},"38":{"tf":1.4142135623730951},"39":{"tf":1.0}}}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"41":{"tf":1.0}}}}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":20,"docs":{"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":2.23606797749979},"13":{"tf":1.4142135623730951},"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"16":{"tf":2.23606797749979},"17":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"19":{"tf":1.4142135623730951},"2":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951},"24":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":2.23606797749979},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"11":{"tf":1.0}}}},"p":{"df":0,"docs":{},"u":{"df":1,"docs":{"41":{"tf":1.0}}}},"r":{"a":{"df":0,"docs":{},"y":{"8":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"d":{".":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"h":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"*":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"u":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"44":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"d":{"df":4,"docs":{"13":{"tf":1.0},"17":{"tf":1.0},"2":{"tf":1.0},"24":{"tf":1.0}}},"df":0,"docs":{}}}},"h":{".":{"2":{"6":{"4":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"29":{"tf":1.0}},"l":{"df":2,"docs":{"25":{"tf":1.0},"33":{"tf":1.0}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"e":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":1,"docs":{"20":{"tf":1.7320508075688772}},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"=":{"7":{"2":{"0":{"df":4,"docs":{"20":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"/":{"/":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.0}}}}}}}}},"df":7,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"2":{"tf":1.4142135623730951},"20":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951}}}}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":4,"docs":{"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"2":{"tf":1.0}}}},"p":{"df":1,"docs":{"18":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"'":{"df":1,"docs":{"14":{"tf":1.0}}},"df":3,"docs":{"11":{"tf":1.0},"18":{"tf":1.7320508075688772},"4":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.4142135623730951}}}}}}},"l":{"df":1,"docs":{"23":{"tf":1.0}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"34":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.7320508075688772}}}}},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"20":{"tf":1.0},"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"20":{"tf":1.4142135623730951},"34":{"tf":2.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":1,"docs":{"44":{"tf":1.0}},"s":{":":{"/":{"/":{"df":0,"docs":{},"f":{".":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{".":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"d":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"2":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":2,"docs":{"14":{"tf":1.0},"18":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"u":{"b":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"/":{"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":0,"docs":{},"l":{"a":{"b":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"/":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"/":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"/":{"<":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{">":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"u":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}}}},"i":{".":{"df":2,"docs":{"18":{"tf":1.0},"23":{"tf":1.0}}},"/":{"df":0,"docs":{},"o":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}}}}},"m":{"a":{"df":0,"docs":{},"g":{"df":3,"docs":{"22":{"tf":1.0},"40":{"tf":1.4142135623730951},"46":{"tf":1.0}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":8,"docs":{"12":{"tf":1.0},"23":{"tf":1.0},"26":{"tf":1.0},"33":{"tf":1.0},"35":{"tf":1.4142135623730951},"40":{"tf":1.0},"46":{"tf":1.0},"9":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":9,"docs":{"10":{"tf":1.4142135623730951},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"2":{"tf":1.7320508075688772},"32":{"tf":1.0},"40":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"37":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"37":{"tf":1.0}}}}}}},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":3,"docs":{"18":{"tf":1.7320508075688772},"20":{"tf":1.4142135623730951},"22":{"tf":1.0}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}},"r":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":3,"docs":{"0":{"tf":1.0},"23":{"tf":1.0},"33":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"l":{"df":9,"docs":{"10":{"tf":1.4142135623730951},"11":{"tf":1.0},"13":{"tf":1.7320508075688772},"17":{"tf":1.7320508075688772},"5":{"tf":1.0},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951},"8":{"tf":1.0},"9":{"tf":1.0}}},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"n":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"a":{"d":{"df":2,"docs":{"15":{"tf":1.0},"18":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"t":{"(":{"c":{"a":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"v":{"2":{".":{"c":{"a":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}}}}},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":4,"docs":{"18":{"tf":1.0},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951},"40":{"tf":1.0}},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"18":{"tf":1.0}},"r":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"f":{"a":{"c":{"df":5,"docs":{"0":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"4":{"tf":1.4142135623730951},"45":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"n":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.4142135623730951}}}}}}},"r":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":1,"docs":{"22":{"tf":1.0}},"t":{"df":5,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"2":{"tf":1.0},"3":{"tf":1.0},"4":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"p":{"c":{"df":1,"docs":{"33":{"tf":2.449489742783178}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"35":{"tf":1.0}}}}},"t":{"'":{"df":3,"docs":{"18":{"tf":1.0},"23":{"tf":1.0},"26":{"tf":1.0}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":2,"docs":{"11":{"tf":1.0},"22":{"tf":1.0}}}}}}}},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"(":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":3,"docs":{"19":{"tf":1.0},"23":{"tf":1.0},"31":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951}}}}}}},"k":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}}}}},"df":0,"docs":{}}},"l":{"a":{"b":{"df":1,"docs":{"0":{"tf":1.0}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"u":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"23":{"tf":2.0},"4":{"tf":1.0}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"22":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"20":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"22":{"tf":1.0},"34":{"tf":1.0},"4":{"tf":1.0}}}}}},"z":{"df":0,"docs":{},"y":{"/":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"35":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"'":{"df":1,"docs":{"19":{"tf":1.0}}},"df":1,"docs":{"18":{"tf":1.4142135623730951}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"23":{"tf":1.0},"33":{"tf":1.0}}}}}},"i":{"b":{")":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"25":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"a":{"df":0,"docs":{},"v":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{},"f":{"d":{"df":0,"docs":{},"k":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"v":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}}}}},"r":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":9,"docs":{"11":{"tf":1.0},"23":{"tf":2.449489742783178},"25":{"tf":1.7320508075688772},"26":{"tf":1.0},"4":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":1.0},"45":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":4,"docs":{"23":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":4,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"4":{"tf":1.0}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":3,"docs":{"23":{"tf":1.0},"38":{"tf":1.0},"4":{"tf":1.0}}},"k":{"df":5,"docs":{"11":{"tf":1.0},"15":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"27":{"tf":1.0}}}},"s":{"df":0,"docs":{},"t":{"[":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"41":{"tf":1.0},"43":{"tf":1.0}}}}},"o":{"a":{"d":{"df":2,"docs":{"19":{"tf":1.4142135623730951},"22":{"tf":1.0}}},"df":0,"docs":{}},"c":{"a":{"df":0,"docs":{},"l":{"df":3,"docs":{"23":{"tf":1.0},"44":{"tf":1.0},"9":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.0}}}}},"m":{"a":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"45":{"tf":1.0}}}}}},"k":{"df":0,"docs":{},"e":{"df":1,"docs":{"40":{"tf":1.0}}}},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"43":{"tf":1.0}}}},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"18":{"tf":1.0}}}},"t":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"36":{"tf":1.0}}}}}}}},"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"18":{"tf":1.0},"32":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"i":{"a":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"d":{"=":{"\"":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"k":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"f":{"_":{"df":0,"docs":{},"u":{"d":{"df":0,"docs":{},"f":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"d":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"32":{"tf":1.0},"35":{"tf":1.0}}}}},"o":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"22":{"tf":2.23606797749979},"4":{"tf":1.0}}}},"u":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}},"df":1,"docs":{"35":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":1,"docs":{"45":{"tf":1.0}}}},"v":{"df":1,"docs":{"43":{"tf":1.0}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"25":{"tf":1.0}}}}}}},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"46":{"tf":1.0}}}}}}}},"p":{"4":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}},"m":{"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"i":{"a":{"df":1,"docs":{"26":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}},"p":{"df":0,"docs":{},"l":{"df":2,"docs":{"18":{"tf":1.0},"34":{"tf":1.0}}}}}}}},"v":{"df":1,"docs":{"10":{"tf":1.0}}},"y":{"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"/":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{":":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"v":{"df":0,"docs":{},"f":{".":{"df":0,"docs":{},"u":{"d":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}}},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":4,"docs":{"18":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":2.0}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}},"e":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"d":{"df":4,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0},"35":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"13":{"tf":1.0}}}}}}},"w":{"df":1,"docs":{"40":{"tf":1.4142135623730951}},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"40":{"tf":1.0}}}}},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"25":{"tf":1.0}},"e":{"df":2,"docs":{"15":{"tf":1.0},"32":{"tf":1.7320508075688772}}}},"t":{"df":0,"docs":{},"e":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":3,"docs":{"15":{"tf":1.7320508075688772},"18":{"tf":1.0},"21":{"tf":1.0}}}}}},"df":2,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0}}}},"w":{"df":4,"docs":{"18":{"tf":2.0},"19":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.0}}}},"u":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"36":{"tf":1.0}}}}}}},"o":{"b":{"df":0,"docs":{},"j":{"df":1,"docs":{"31":{"tf":1.0}},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":1,"docs":{"14":{"tf":1.0}},"n":{"df":2,"docs":{"32":{"tf":1.0},"34":{"tf":1.0}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"v":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"39":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"g":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"c":{"df":1,"docs":{"38":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}}}}},"/":{"c":{"df":0,"docs":{},"v":{"2":{"df":7,"docs":{"28":{"tf":1.0},"35":{"tf":1.7320508075688772},"36":{"tf":1.0},"37":{"tf":1.0},"38":{"tf":1.0},"39":{"tf":1.0},"46":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":9,"docs":{"11":{"tf":1.0},"12":{"tf":1.0},"2":{"tf":1.0},"26":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.4142135623730951},"4":{"tf":1.0},"46":{"tf":1.0}}}},"d":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}},"df":4,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"2":{"tf":1.0},"4":{"tf":1.0}}}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":1,"docs":{"22":{"tf":1.0}}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.7320508075688772}}}}}},"r":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":1,"docs":{"46":{"tf":1.0}}}}}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"18":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"0":{"tf":1.0}}}},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"14":{"tf":1.0}}},"t":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":5,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"23":{"tf":1.4142135623730951},"41":{"tf":1.0}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":5,"docs":{"18":{"tf":2.0},"19":{"tf":1.0},"22":{"tf":1.0},"36":{"tf":1.0},"40":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"19":{"tf":1.0},"20":{"tf":1.0},"23":{"tf":1.0},"40":{"tf":1.0}},"l":{"a":{"df":0,"docs":{},"y":{"df":2,"docs":{"19":{"tf":1.0},"21":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":1,"docs":{"12":{"tf":1.0}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}}},"r":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"15":{"tf":1.0}}}}},"df":1,"docs":{"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"31":{"tf":1.0}}}}}}},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"7":{"tf":1.0}},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"t":{"df":1,"docs":{"4":{"tf":1.0}}},"x":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"b":{"2":{"4":{"df":2,"docs":{"32":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":3,"docs":{"18":{"tf":1.0},"20":{"tf":1.0},"32":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":3,"docs":{"22":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}}},"l":{"a":{"c":{"df":0,"docs":{},"e":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"23":{"tf":1.0}}}},"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}},"y":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":6,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":2.6457513110645907},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"36":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"r":{"df":0,"docs":{},"t":{"=":{"8":{"0":{"0":{"0":{"df":2,"docs":{"18":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"41":{"tf":1.0}}}}}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":2,"docs":{"1":{"tf":1.0},"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.7320508075688772}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"40":{"tf":1.0}}}}}},"i":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}}},"df":3,"docs":{"18":{"tf":1.4142135623730951},"40":{"tf":1.0},"9":{"tf":1.0}}}}},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":5,"docs":{"1":{"tf":1.0},"23":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"46":{"tf":1.0}}}}}},"df":1,"docs":{"4":{"tf":1.0}},"g":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"45":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":3,"docs":{"12":{"tf":1.0},"23":{"tf":1.0},"35":{"tf":1.0}}}}}}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":4,"docs":{"0":{"tf":1.0},"23":{"tf":1.4142135623730951},"4":{"tf":1.4142135623730951},"40":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"44":{"tf":1.0}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"0":{"tf":1.0},"23":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":1,"docs":{"24":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"9":{"tf":1.0}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}},"y":{"df":10,"docs":{"16":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":2.23606797749979},"3":{"tf":1.0},"33":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.4142135623730951}},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"0":{"tf":1.0},"24":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":6,"docs":{"2":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"1":{"tf":1.0},"4":{"tf":1.0}}}}},"i":{"c":{"df":0,"docs":{},"k":{"df":3,"docs":{"2":{"tf":1.4142135623730951},"24":{"tf":1.0},"25":{"tf":1.0}}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"(":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"2":{"4":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.0}}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"22":{"tf":1.0}}}}}}},"df":1,"docs":{"19":{"tf":1.0}},"e":{"a":{"d":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":1,"docs":{"23":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"34":{"tf":1.0}}}}}},"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"18":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":1,"docs":{"38":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":3,"docs":{"23":{"tf":1.0},"45":{"tf":1.0},"9":{"tf":1.4142135623730951}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"l":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.4142135623730951}}}}},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"40":{"tf":1.0}}}},"df":5,"docs":{"15":{"tf":1.0},"18":{"tf":2.0},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"l":{"a":{"c":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":1,"docs":{"11":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":3,"docs":{"1":{"tf":1.0},"22":{"tf":2.0},"23":{"tf":1.0}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"33":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"r":{"df":4,"docs":{"11":{"tf":1.0},"27":{"tf":1.0},"34":{"tf":1.0},"6":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"22":{"tf":1.0},"32":{"tf":1.0}}}}}},"t":{"df":1,"docs":{"23":{"tf":1.0}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":10,"docs":{"1":{"tf":1.4142135623730951},"13":{"tf":1.0},"15":{"tf":1.7320508075688772},"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}}},"t":{"df":1,"docs":{"45":{"tf":1.0}}}}},"t":{"df":3,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"1":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":7,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"22":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"40":{"tf":2.6457513110645907}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"g":{"b":{"2":{"4":{"df":3,"docs":{"22":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"20":{"tf":1.0},"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":1,"docs":{"33":{"tf":1.0}}}}}},"m":{"df":1,"docs":{"9":{"tf":1.0}}},"o":{"a":{"d":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"p":{"df":1,"docs":{"41":{"tf":1.7320508075688772}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"u":{"df":0,"docs":{},"n":{"df":4,"docs":{"15":{"tf":1.0},"33":{"tf":1.0},"43":{"tf":1.0},"9":{"tf":1.0}}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.0},"26":{"tf":1.0}},"y":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"27":{"tf":1.0}}}}}}}}},"df":0,"docs":{}}}}}},"s":{"3":{"df":1,"docs":{"44":{"tf":1.0}}},"a":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":1,"docs":{"26":{"tf":1.0}}}},"m":{"df":0,"docs":{},"e":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"33":{"tf":1.0}}},"p":{"df":0,"docs":{},"l":{"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"e":{"df":4,"docs":{"13":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"9":{"tf":1.0}}}}},"c":{"a":{"df":0,"docs":{},"l":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"32":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"[":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}}},"df":4,"docs":{"23":{"tf":1.4142135623730951},"32":{"tf":2.0},"40":{"tf":1.0},"41":{"tf":1.0}}}}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"a":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"2":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":4,"docs":{"12":{"tf":1.0},"13":{"tf":1.0},"17":{"tf":1.0},"35":{"tf":1.0}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}}}},"r":{"df":0,"docs":{},"v":{"df":2,"docs":{"23":{"tf":1.0},"45":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":9,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.7320508075688772},"23":{"tf":2.6457513110645907},"33":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":1.7320508075688772}}}},"i":{"c":{"df":3,"docs":{"23":{"tf":1.0},"26":{"tf":1.0},"44":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"32":{"tf":1.0}}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"29":{"tf":1.0}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"43":{"tf":1.0}}}},"w":{"df":1,"docs":{"21":{"tf":1.0}}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"22":{"tf":1.0},"23":{"tf":1.0},"40":{"tf":1.0}}}}},"z":{"df":0,"docs":{},"e":{"=":{"4":{"8":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"k":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"15":{"tf":1.0}}}}},"n":{"a":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"r":{"c":{"df":7,"docs":{"11":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"36":{"tf":1.0},"4":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"'":{"df":1,"docs":{"22":{"tf":1.4142135623730951}}},".":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":7,"docs":{"18":{"tf":1.7320508075688772},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":2.0},"36":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0}},"i":{"df":0,"docs":{},"f":{"df":3,"docs":{"1":{"tf":1.7320508075688772},"23":{"tf":1.0},"36":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"e":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}}}},"q":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{},"n":{"d":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"t":{"df":22,"docs":{"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":2.23606797749979},"13":{"tf":1.4142135623730951},"14":{"tf":1.4142135623730951},"15":{"tf":1.7320508075688772},"16":{"tf":2.23606797749979},"17":{"tf":1.4142135623730951},"18":{"tf":2.23606797749979},"19":{"tf":1.4142135623730951},"2":{"tf":2.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951},"23":{"tf":1.0},"24":{"tf":1.0},"29":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":2.23606797749979},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}}},"t":{"df":0,"docs":{},"u":{"df":3,"docs":{"37":{"tf":1.4142135623730951},"38":{"tf":1.0},"39":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"46":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{}}},"r":{"df":3,"docs":{"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}},"e":{"a":{"df":0,"docs":{},"m":{"/":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"13":{"tf":1.0}}}},"df":0,"docs":{}}}},"=":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"15":{"tf":1.7320508075688772},"18":{"tf":1.0},"23":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"26":{"tf":1.0}}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":2,"docs":{"23":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}}},"u":{"b":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}}}}},"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"22":{"tf":1.7320508075688772}}}},"d":{"df":0,"docs":{},"o":{"df":1,"docs":{"10":{"tf":1.7320508075688772}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.4142135623730951}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":1,"docs":{"41":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":5,"docs":{"33":{"tf":1.0},"35":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":2.0},"44":{"tf":1.0}}}}}}}},"y":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":2,"docs":{"22":{"tf":1.0},"23":{"tf":1.0}}}}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":3,"docs":{"22":{"tf":1.0},"23":{"tf":1.0},"46":{"tf":1.0}},"s":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"25":{"tf":1.0}}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":3,"docs":{"0":{"tf":1.0},"23":{"tf":1.7320508075688772},"33":{"tf":1.0}}}}}}}},"t":{"a":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":3,"docs":{"18":{"tf":1.0},"22":{"tf":1.0},"40":{"tf":1.0}}}},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"27":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"k":{"df":2,"docs":{"22":{"tf":1.0},"46":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"21":{"tf":1.4142135623730951}}}}}}}}},"n":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"41":{"tf":1.0}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}},"x":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"30":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":3,"docs":{"22":{"tf":1.0},"30":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"20":{"tf":1.0}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":1,"docs":{"6":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":3,"docs":{"18":{"tf":1.7320508075688772},"19":{"tf":1.0},"22":{"tf":1.7320508075688772}}}}},"df":0,"docs":{}}}}}},"o":{"df":1,"docs":{"18":{"tf":1.0}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"23":{"tf":1.0},"34":{"tf":1.0},"4":{"tf":1.0}}}}}},"o":{"df":0,"docs":{},"l":{"df":6,"docs":{"23":{"tf":2.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.0},"4":{"tf":1.0}}}},"s":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.4142135623730951},"19":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"[":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.0},"19":{"tf":1.0}}}},"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":6,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.4142135623730951},"23":{"tf":1.0},"25":{"tf":1.4142135623730951},"32":{"tf":1.0},"4":{"tf":1.0}}}}}},"p":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"1":{"tf":1.0},"23":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":1,"docs":{"1":{"tf":1.0}}}}}}}},"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"34":{"tf":1.0}}},"u":{"df":0,"docs":{},"e":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"y":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":3,"docs":{"22":{"tf":1.0},"32":{"tf":1.0},"40":{"tf":1.0}}}}}},"u":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"2":{"2":{".":{"0":{"4":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"d":{"df":0,"docs":{},"f":{"df":3,"docs":{"28":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.7320508075688772}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":1,"docs":{"40":{"tf":1.0}}}},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":1,"docs":{"23":{"tf":1.0}},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"33":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"l":{"df":1,"docs":{"9":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"b":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"(":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{":":{"/":{"/":{"df":0,"docs":{},"f":{".":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{".":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"d":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"2":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":1,"docs":{"19":{"tf":1.0}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"s":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":20,"docs":{"1":{"tf":1.0},"10":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":2.23606797749979},"2":{"tf":1.0},"22":{"tf":1.4142135623730951},"23":{"tf":2.8284271247461903},"24":{"tf":1.0},"26":{"tf":1.7320508075688772},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.7320508075688772},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.4142135623730951},"6":{"tf":1.0},"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":6,"docs":{"21":{"tf":1.4142135623730951},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":2.0},"41":{"tf":1.0}}}},"r":{"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"/":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"v":{"2":{"df":0,"docs":{},"v":{"df":1,"docs":{"22":{"tf":1.0}}}},"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":1,"docs":{"32":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"b":{"df":0,"docs":{},"m":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":3,"docs":{"0":{"tf":1.4142135623730951},"24":{"tf":1.0},"25":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}}}}},"f":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"df":1,"docs":{"19":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"h":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"'":{"df":0,"docs":{},"s":{"c":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"(":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"u":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"40":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"y":{"df":0,"docs":{},"r":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":1,"docs":{"10":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"\"":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"\"":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"'":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}}}},"df":4,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.0},"40":{"tf":1.0},"9":{"tf":1.0}},"r":{"df":1,"docs":{"18":{"tf":1.0}}}},"i":{"a":{"df":2,"docs":{"23":{"tf":1.0},"35":{"tf":1.0}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"'":{"df":1,"docs":{"18":{"tf":1.0}}},"c":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"37":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":19,"docs":{"0":{"tf":1.7320508075688772},"1":{"tf":2.0},"14":{"tf":1.0},"15":{"tf":2.0},"18":{"tf":3.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.7320508075688772},"23":{"tf":2.8284271247461903},"25":{"tf":2.23606797749979},"26":{"tf":1.4142135623730951},"36":{"tf":1.0},"4":{"tf":2.0},"43":{"tf":1.4142135623730951},"44":{"tf":1.4142135623730951},"45":{"tf":1.0},"46":{"tf":1.0},"9":{"tf":1.0}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"36":{"tf":1.0},"37":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":1,"docs":{"36":{"tf":1.0}}},"df":0,"docs":{}}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"c":{"df":1,"docs":{"37":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":30,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":2.23606797749979},"10":{"tf":2.0},"11":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":1.0},"16":{"tf":1.0},"18":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":3.0},"24":{"tf":2.449489742783178},"25":{"tf":1.4142135623730951},"28":{"tf":1.0},"29":{"tf":1.0},"3":{"tf":1.4142135623730951},"32":{"tf":1.0},"33":{"tf":1.0},"36":{"tf":1.4142135623730951},"4":{"tf":3.3166247903554},"40":{"tf":2.0},"41":{"tf":1.0},"43":{"tf":2.449489742783178},"44":{"tf":1.0},"45":{"tf":2.6457513110645907},"46":{"tf":1.7320508075688772},"5":{"tf":1.0},"6":{"tf":1.7320508075688772},"7":{"tf":1.7320508075688772},"8":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"r":{"'":{"df":1,"docs":{"2":{"tf":1.0}}},".":{"c":{"df":0,"docs":{},"v":{"2":{"df":6,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.0},"2":{"tf":1.4142135623730951},"24":{"tf":1.0},"35":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"_":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"'":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.4142135623730951}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"o":{"d":{"df":1,"docs":{"23":{"tf":2.23606797749979}}},"df":0,"docs":{}},"p":{"8":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":1,"docs":{"18":{"tf":1.0}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"*":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":2,"docs":{"20":{"tf":1.4142135623730951},"34":{"tf":1.7320508075688772}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"w":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"k":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":2,"docs":{"12":{"tf":1.0},"16":{"tf":1.0}}}}}}}}}}},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"18":{"tf":1.0},"23":{"tf":1.7320508075688772},"9":{"tf":1.0}}}},"y":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":1,"docs":{"20":{"tf":1.7320508075688772}},"e":{"b":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"41":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"3":{"tf":1.0},"4":{"tf":1.0}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"l":{"df":2,"docs":{"18":{"tf":1.0},"43":{"tf":1.0}}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"10":{"tf":1.0}}}}},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"=":{"1":{"2":{"8":{"0":{"df":4,"docs":{"20":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}}},"df":7,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"2":{"tf":1.4142135623730951},"20":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.0}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"k":{"df":11,"docs":{"12":{"tf":1.0},"13":{"tf":1.4142135623730951},"15":{"tf":1.0},"18":{"tf":1.7320508075688772},"23":{"tf":1.4142135623730951},"26":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.4142135623730951},"43":{"tf":1.4142135623730951},"44":{"tf":1.0},"45":{"tf":1.7320508075688772}},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}}}},"l":{"d":{"df":6,"docs":{"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"2":{"tf":1.0},"30":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"15":{"tf":1.0},"23":{"tf":1.4142135623730951}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"26":{"tf":1.0}}}}}}}}},"x":{"1":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"2":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"=":{"1":{"0":{"0":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"10":{"tf":1.0}}},"y":{"1":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"2":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"=":{"1":{"0":{"0":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"10":{"tf":1.0}},"e":{"df":1,"docs":{"44":{"tf":1.0}}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"4":{"tf":1.0}}}},"u":{"'":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"35":{"tf":1.0}}}}}}}}},"r":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":3,"docs":{"23":{"tf":2.23606797749979},"6":{"tf":1.0},"9":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":3,"docs":{"18":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"title":{"root":{"a":{"c":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"44":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":1.0}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"19":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"df":1,"docs":{"31":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"x":{"df":1,"docs":{"19":{"tf":1.0}}}},"u":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"d":{"df":2,"docs":{"11":{"tf":1.0},"27":{"tf":1.0}}},"df":0,"docs":{},"t":{"df":1,"docs":{"29":{"tf":1.0}}}}}}},"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"8":{"tf":1.0}}}},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"45":{"tf":1.0},"46":{"tf":1.0}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}}}}}}}},"n":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"df":0,"docs":{}}},"v":{"2":{"df":1,"docs":{"12":{"tf":1.0}}},"df":0,"docs":{}}},"d":{"a":{"df":0,"docs":{},"t":{"a":{"df":3,"docs":{"0":{"tf":1.0},"22":{"tf":1.0},"25":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"21":{"tf":1.0},"40":{"tf":1.0}}}}}},"o":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"9":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"3":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"r":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"30":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"l":{"df":1,"docs":{"16":{"tf":1.0}}}}},"df":0,"docs":{},"f":{"a":{"df":0,"docs":{},"q":{"df":1,"docs":{"42":{"tf":1.0}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"45":{"tf":1.0}}}}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"21":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"40":{"tf":1.0}}}}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"43":{"tf":1.0}}}},"df":0,"docs":{}}}},"u":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"35":{"tf":1.0},"36":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":3,"docs":{"12":{"tf":1.0},"16":{"tf":1.0},"5":{"tf":1.0}}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":2,"docs":{"14":{"tf":1.0},"18":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"l":{"df":3,"docs":{"13":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.0}}}}}}}}},"p":{"c":{"df":1,"docs":{"33":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"25":{"tf":1.0}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"m":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"v":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"39":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"g":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"c":{"df":1,"docs":{"38":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"/":{"c":{"df":0,"docs":{},"v":{"2":{"df":2,"docs":{"35":{"tf":1.0},"46":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":1,"docs":{"37":{"tf":1.0}}}},"df":0,"docs":{}}}}},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{}}}}},"y":{"df":2,"docs":{"24":{"tf":1.0},"7":{"tf":1.0}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"o":{"a":{"d":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"p":{"df":1,"docs":{"41":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"s":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":1,"docs":{"32":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":1,"docs":{"36":{"tf":1.0}}}}},"df":0,"docs":{}}},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":4,"docs":{"12":{"tf":1.0},"16":{"tf":1.0},"2":{"tf":1.0},"5":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"15":{"tf":1.0}}}},"df":0,"docs":{}}}},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"43":{"tf":1.0}}}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"21":{"tf":1.0}}}}}}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}}}}},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":2,"docs":{"0":{"tf":1.0},"25":{"tf":1.0}}}}}}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"21":{"tf":1.0},"40":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"df":4,"docs":{"0":{"tf":1.0},"25":{"tf":1.0},"43":{"tf":1.0},"44":{"tf":1.0}}}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":11,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"36":{"tf":1.0},"43":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":1,"docs":{"21":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"d":{"df":2,"docs":{"14":{"tf":1.0},"18":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"lang":"English","pipeline":["trimmer","stopWordFilter","stemmer"],"ref":"id","version":"0.9.5"},"results_options":{"limit_results":30,"teaser_word_count":30},"search_options":{"bool":"OR","expand":true,"fields":{"body":{"boost":1},"breadcrumbs":{"boost":1},"title":{"boost":2}}}}); \ No newline at end of file diff --git a/searchindex.json b/searchindex.json new file mode 100644 index 0000000..211d978 --- /dev/null +++ b/searchindex.json @@ -0,0 +1 @@ +{"doc_urls":["introduction.html#vidformer---video-data-transformation","introduction.html#-why-vidformer","introduction.html#-quick-start","introduction.html#-documentation","introduction.html#-about-the-project","getting-started.html#getting-started","install.html#install","install.html#vidformer-py","install.html#vidformer-cli","install.html#-docker","install.html#precompiled-binary","install.html#build-from-sources","getting-started-cv2.html#getting-started---cv2","getting-started-cv2.html#installation","getting-started-cv2.html#hello-world","getting-started-cv2.html#stream-the-results","getting-started-dsl.html#getting-started---dsl","getting-started-dsl.html#installation","getting-started-dsl.html#hello-world","getting-started-dsl.html#bounding-boxes","getting-started-dsl.html#composition","getting-started-dsl.html#viewing-telemetry-and-user-defined-filters","concepts.html#concepts--data-model","tools.html#the-vidformer-tools","vidformer-py.html#vidformer-py","libvidformer.html#vidformer---video-data-transformation-library","libvidformer.html#about","libvidformer.html#building","filters.html#filters","builtin-filters.html#built-in-filters","builtin-filters.html#drawtext","builtin-filters.html#boundingbox","builtin-filters.html#scale","builtin-filters.html#ipc","builtin-filters.html#hstack--vstack","opencv-filters.html#opencvcv2-functions","opencv-filters.html#vidformer-specific-functions","opencv-filters.html#opencv","opencv-filters.html#opencvimgproc","opencv-filters.html#opencvcore","udf-filters.html#user-defined-filters","roadmap.html#roadmap","faq.html#faq","faq.html#what-video-formats-does-vidformer-support","faq.html#can-i-access-remote-videos-on-the-internet","faq.html#how-does-vidformer-compare-to-ffmpeg","faq.html#how-does-vidformer-compare-to-opencvcv2"],"index":{"documentStore":{"docInfo":{"0":{"body":21,"breadcrumbs":5,"title":4},"1":{"body":53,"breadcrumbs":2,"title":1},"10":{"body":48,"breadcrumbs":5,"title":2},"11":{"body":20,"breadcrumbs":5,"title":2},"12":{"body":19,"breadcrumbs":8,"title":3},"13":{"body":18,"breadcrumbs":6,"title":1},"14":{"body":53,"breadcrumbs":7,"title":2},"15":{"body":79,"breadcrumbs":7,"title":2},"16":{"body":7,"breadcrumbs":8,"title":3},"17":{"body":3,"breadcrumbs":6,"title":1},"18":{"body":218,"breadcrumbs":7,"title":2},"19":{"body":48,"breadcrumbs":7,"title":2},"2":{"body":62,"breadcrumbs":3,"title":2},"20":{"body":94,"breadcrumbs":6,"title":1},"21":{"body":12,"breadcrumbs":10,"title":5},"22":{"body":114,"breadcrumbs":6,"title":3},"23":{"body":176,"breadcrumbs":3,"title":2},"24":{"body":29,"breadcrumbs":5,"title":2},"25":{"body":24,"breadcrumbs":7,"title":5},"26":{"body":31,"breadcrumbs":2,"title":0},"27":{"body":11,"breadcrumbs":3,"title":1},"28":{"body":10,"breadcrumbs":2,"title":1},"29":{"body":11,"breadcrumbs":5,"title":2},"3":{"body":7,"breadcrumbs":2,"title":1},"30":{"body":14,"breadcrumbs":4,"title":1},"31":{"body":35,"breadcrumbs":4,"title":1},"32":{"body":51,"breadcrumbs":4,"title":1},"33":{"body":43,"breadcrumbs":4,"title":1},"34":{"body":39,"breadcrumbs":5,"title":2},"35":{"body":27,"breadcrumbs":4,"title":2},"36":{"body":20,"breadcrumbs":5,"title":3},"37":{"body":9,"breadcrumbs":3,"title":1},"38":{"body":19,"breadcrumbs":3,"title":1},"39":{"body":3,"breadcrumbs":3,"title":1},"4":{"body":80,"breadcrumbs":2,"title":1},"40":{"body":147,"breadcrumbs":7,"title":3},"41":{"body":25,"breadcrumbs":2,"title":1},"42":{"body":0,"breadcrumbs":2,"title":1},"43":{"body":37,"breadcrumbs":5,"title":4},"44":{"body":23,"breadcrumbs":5,"title":4},"45":{"body":35,"breadcrumbs":4,"title":3},"46":{"body":16,"breadcrumbs":4,"title":3},"5":{"body":12,"breadcrumbs":4,"title":2},"6":{"body":14,"breadcrumbs":4,"title":1},"7":{"body":3,"breadcrumbs":5,"title":2},"8":{"body":0,"breadcrumbs":5,"title":2},"9":{"body":47,"breadcrumbs":4,"title":1}},"docs":{"0":{"body":"Test PyPI version Crates.io Version Open In Colab License A research project providing infrastructure for video interfaces and pipelines. Developed by the OSU Interactive Data Systems Lab.","breadcrumbs":"Introduction » vidformer - Video Data Transformation","id":"0","title":"vidformer - Video Data Transformation"},"1":{"body":"Vidformer efficiently transforms video data, enabling faster annotation, editing, and processing of video data—without having to focus on performance. It uses a declarative specification format to represent transformations. This enables: ⚡ Transparent Optimization: Vidformer optimizes the execution of declarative specifications just like a relational database optimizes relational queries. ⏳ Lazy/Deferred Execution: Video results can be retrieved on-demand, allowing for practically instantaneous playback of video results. 🔄 Transpilation: Vidformer specifications can be created from existing code (like cv2).","breadcrumbs":"Introduction » 🎯 Why vidformer","id":"1","title":"🎯 Why vidformer"},"10":{"body":"Precompiled binaries are available for vidformer releases . For example: wget https://github.com/ixlab/vidformer/releases/download//vidformer-cli-ubuntu22.04-amd64\nsudo mv vidformer-cli-ubuntu22.04-amd64 /usr/local/bin/vidformer-cli\nsudo chmod +x /usr/local/bin/vidformer-cli\nsudo apt install -y libopencv-dev libfdk-aac-dev To use: import vidformer as vf\nserver = vf.YrdenServer(bin=\"vidformer-cli\") or export VIDFORMER_BIN='vidformer-cli' import vidformer as vf\nserver = vf.YrdenServer()","breadcrumbs":"Getting Started » Install » Precompiled binary:","id":"10","title":"Precompiled binary:"},"11":{"body":"vidformer-cli can be compiled from our git repo with a standard cargo build. This depends on the core vidformer library which itself requires linking to FFmpeg and OpenCV. Details are available here .","breadcrumbs":"Getting Started » Install » Build from Sources","id":"11","title":"Build from Sources"},"12":{"body":"This is a walkthrough of getting started with vidformer OpenCV cv2 compatability layer. ⚠️ Adding cv2 functions is a work in progress. See the cv2 filters page for which functions have been implemented.","breadcrumbs":"Getting Started » Getting Started - cv2 » Getting Started - cv2","id":"12","title":"Getting Started - cv2"},"13":{"body":"See Installation guide Or you can Open In Colab . ⚠️ Due to how Colab networking works, vidformer can't stream/play results in Colab, only save them to disk. cv2.vidplay() will not work!","breadcrumbs":"Getting Started » Getting Started - cv2 » Installation","id":"13","title":"Installation"},"14":{"body":"Copy in your video, or use ours: curl -O https://f.dominik.win/data/dve2/tos_720p.mp4 Then just replace import cv2 with import vidformer.cv2 as cv2. Here's our example script: import vidformer.cv2 as cv2 cap = cv2.VideoCapture(\"tos_720p.mp4\")\nfps = cap.get(cv2.CAP_PROP_FPS)\nwidth = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))\nheight = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) out = cv2.VideoWriter(\"output.mp4\", cv2.VideoWriter_fourcc(*\"mp4v\"), fps, (width, height))\nwhile True: ret, frame = cap.read() if not ret: break cv2.putText(frame, \"Hello, World!\", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 1) out.write(frame) cap.release()\nout.release()","breadcrumbs":"Getting Started » Getting Started - cv2 » Hello, world!","id":"14","title":"Hello, world!"},"15":{"body":"Saving videos to disk works, but we can also display them in the notebook. Since we stream the results and only render them on demand this can start practically instantly! First, replace \"output.mp4\" with None to skip writing the video to disk. Then you can use cv2.vidplay() to play the video! import vidformer.cv2 as cv2 cap = cv2.VideoCapture(\"tos_720p.mp4\")\nfps = cap.get(cv2.CAP_PROP_FPS)\nwidth = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))\nheight = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) out = cv2.VideoWriter(None, cv2.VideoWriter_fourcc(*\"mp4v\"), fps, (width, height))\nwhile True: ret, frame = cap.read() if not ret: break cv2.putText(frame, \"Hello, World!\", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 1) out.write(frame) cap.release()\nout.release() cv2.vidplay(out) ⚠️ By default cv2.vidplay() will return a video which plays in a Jupyter Notebook. If running outside a jupyter notebook you can pass method=\"link\" to return a link instead.","breadcrumbs":"Getting Started » Getting Started - cv2 » Stream the Results","id":"15","title":"Stream the Results"},"16":{"body":"This is a walkthrough of getting started with vidformer-py core DSL.","breadcrumbs":"Getting Started » Getting Started - DSL » Getting Started - DSL","id":"16","title":"Getting Started - DSL"},"17":{"body":"See Installation guide","breadcrumbs":"Getting Started » Getting Started - DSL » Installation","id":"17","title":"Installation"},"18":{"body":"⚠️ We assume this is in a Jupyter notebook. If not then .play() won't work and you have to use .save() instead. We start by connecting to a server and registering a source: import vidformer as vf\nfrom fractions import Fraction server = vf.YrdenServer(domain='localhost', port=8000) tos = vf.Source( server, \"tos_720p\", # name (for pretty printing) \"https://f.dominik.win/data/dve2/tos_720p.mp4\", stream=0, # index of the video stream we want to use\n) print(tos.ts())\nprint(tos.fmt()) This will print the timestamps of all the frames in the video, and then format information: This may take a few seconds the first time, but frame times are cached afterwords. > [Fraction(0, 1), Fraction(1, 24), Fraction(1, 12), Fraction(1, 8), ...]\n> {'width': 1280, 'height': 720, 'pix_fmt': 'yuv420p'} Now lets create a 30 second clip starting at the 5 minute mark. The source video is at at a constant 24 FPS, so lets create a 24 FPS output as well: domain = [Fraction(i, 24) for i in range(24 * 30)] Now we need to render each of these frames, so we define a render function. def render(t: Fraction, i: int): clip_start_point = Fraction(5 * 60, 1) # start at 5 * 60 seconds return tos[t + clip_start_point] We used timestamp-based indexing here, but you can also use integer indexing (tos.iloc[i + 5 * 60 * 24]). Now we can create a spec and play it in the browser. We create a spec from the resulting video's frame timestamps (domain), a function to construct each output frame (render), and the output videos format (matching tos.fmt()). spec = vf.Spec(domain, render, tos.fmt())\nspec.play(server) This plays this result: Some Jupyter environments are weird (i.e., VS Code), so .play() might not work. Using .play(..., method=\"iframe\") may help. It's worth noting that we are playing frames in order here and outputing video at the same framerate we recieved, but that doesn't need to be the case. Here are some things other things you can now try: Reversing the video Double the speed of the video Either double the framerate or sample every other frame Shuffle the frames into a random order Combining frames from multiple videos Create a variable frame rate video Note: .play() will not work with VFR, but .save() will.","breadcrumbs":"Getting Started » Getting Started - DSL » Hello, world!","id":"18","title":"Hello, world!"},"19":{"body":"Now let's overlay some bouding boxes over the entire clip: # Load some data\nimport urllib.request, json with urllib.request.urlopen(\"https://f.dominik.win/data/dve2/tos_720p-objects.json\") as r: detections_per_frame = json.load(r) bbox = vf.Filter(\"BoundingBox\") # load the built-in BoundingBox filter domain = tos.ts() # output should have same frame timestamps as our example clip def render(t, i): return bbox( tos[t], bounds=detections_per_frame[i]) spec = vf.Spec(domain, render, tos.fmt())\nspec.play(server) This plays this result (video is just a sample clip):","breadcrumbs":"Getting Started » Getting Started - DSL » Bounding Boxes","id":"19","title":"Bounding Boxes"},"2":{"body":"Open In Colab The easiest way to get started is using vidformer's cv2 frontend, which allows most Python OpenCV visualization scripts to replace import cv2 with import vidformer.cv2 as cv2: import vidformer.cv2 as cv2 cap = cv2.VideoCapture(\"my_input.mp4\")\nfps = cap.get(cv2.CAP_PROP_FPS)\nwidth = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))\nheight = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) out = cv2.VideoWriter(\"my_output.mp4\", cv2.VideoWriter_fourcc(*\"mp4v\"), fps, (width, height))\nwhile True: ret, frame = cap.read() if not ret: break cv2.putText(frame, \"Hello, World!\", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 1) out.write(frame) cap.release()\nout.release() You can find details on this in our Getting Started Guide .","breadcrumbs":"Introduction » 🚀 Quick Start","id":"2","title":"🚀 Quick Start"},"20":{"body":"We can place frames next to each other with the HStack and VStack filters. For example, HStack(left_frame, middle_frame, right_frame, width=1280, height=720, format=\"yuv420p\") will place three frames side-by-side. As a larger example, we can view a window function over frames as a 5x5 grid: hstack = vf.Filter(\"HStack\")\nvstack = vf.Filter(\"VStack\") w, h = 1920, 1080 def create_grid(tos, i, N, width, height, fmt=\"yuv420p\"): grid = [] for row in range(N): columns = [] for col in range(N): index = row * N + col columns.append(tos.iloc[i + index]) grid.append(hstack(*columns, width=width, height=height//N, format=fmt)) final_grid = vstack(*grid, width=width, height=height, format=fmt) return final_grid domain = [Fraction(i, 24) for i in range(0, 5000)] def render(t, i): return create_grid(tos, i, 5, w, h) fmt = {'width': w, 'height': h, 'pix_fmt': 'yuv420p'} spec = vf.Spec(domain, render, fmt)\nspec.play(server) This plays this result (video is just a sample clip):","breadcrumbs":"Getting Started » Getting Started - DSL » Composition","id":"20","title":"Composition"},"21":{"body":"This notebook shows how to build custom filters to overlay data. This plays this result (video is just a sample clip):","breadcrumbs":"Getting Started » Getting Started - DSL » Viewing Telemetry (and User-Defined Filters)","id":"21","title":"Viewing Telemetry (and User-Defined Filters)"},"22":{"body":"vidformer builds on the data model introduced in the V2V paper . Frames are a single image. Frames are represented as their resolution and pixel format (the type and layout of pixels in memory, such as rgb24, gray8, or yuv420p). Videos are sequences of frames represented as an array. We index these arrays by rational numbers corresponding to their timestamp. Filters are functions which construct a frame. Filters can take inputs, such as frames or data. For example, DrawText may draw some text on a frame. Specs declarativly represent a video synthesis task. They represent the construction of a result videos, which is itself modeled as an array. Specs primairly contan domain and render functions. A spec's domain function returns the timestamps of the output frames. A spec's render function returns a composition of filters used to construct a frame at a spesific timestamp. Data Arrays allow using data in specs symbolically, as opposed to inserting constants directly into the spec. These allow for deduplication and loading large data blobs efficiently. Data Arrays can be backed by external data sources, such as SQL databases.","breadcrumbs":"Concepts & Data Model » Concepts & Data Model","id":"22","title":"Concepts & Data Model"},"23":{"body":"vidformer is a highly modular suite of tools that work together: vidformer-py : A Python 🐍 client for declarative video synthesis Provides an easy-to-use library for symbolically representing transformed videos Acts as a client for a VoD server (i.e., for yrden) Using vidformer-py is the best place to get started libvidformer : The core data-oriented declarative video editing library An embedded video processing execution engine with low-level interfaces Systems code, written in Rust 🦀 You should use if: You are building a VDBMS or other multimodal data-system infrastructure. You should not use if: You just want to use vidformer in your workflows or projects. yrden : A vidformer Video-on-Demand server Provides vidformer services over a REST-style API Allows for client libraries to be written in any language Serves video results via HLS streams Designed for local single-tenant use You should use if: You want to create faster video results in your workflows or projects. Note that yrden servers may be spun up transparently by client libraries, so you might use yrden without realizing it. igni : A planned scale-out Video-on-Demand server Will allow for scalable and secure public-facing VOD endpoints Client libraries in other languages: Writing a vidformer client library for other languages is simple. It's a few hundred lines of code, and you just have to construct some JSON. Contributions or suggestions for other languages are welcome. Other VoD servers: We provide yrden as a simple reference VoD server implementation. If you want to scale-out deployments, multi-tenant deployments, or deep integration with a specific system, writing another VoD server is needed. (In progress work)","breadcrumbs":"Tools » The vidformer Tools","id":"23","title":"The vidformer Tools"},"24":{"body":"PyPI version License vidformer-py is a Python 🐍 interface for vidformer . Our getting started guide explains how to use it. Quick links: 📦 PyPI 📘 Documentation - vidformer-py 📘 Documentation - vidformer.cv2 🧑‍💻 Source Code Publish: export FLIT_USERNAME='__token__' FLIT_PASSWORD=''\nflit publish","breadcrumbs":"Tools » vidformer-py » vidformer-py","id":"24","title":"vidformer-py"},"25":{"body":"Crates.io Version License (lib)vidformer is a core video synthesis/transformation library. It handles the movement, control flow, and processing of video and conventional (non-video) data. Quick links: 📦 Crates.io 📘 Documentation 🧑‍💻 Source Code","breadcrumbs":"Tools » libvidformer » vidformer - Video Data Transformation Library","id":"25","title":"vidformer - Video Data Transformation Library"},"26":{"body":"It's written in Rust 🦀 So it does some fancy parallel processing and does so safely Uses the FFmpeg libav libraries for multimedia stuff So it should work with nearly every video file ever made Uses Apache OpenDAL for I/O So it can access videos in a bunch of storage services Implements filters using OpenCV","breadcrumbs":"Tools » libvidformer » About","id":"26","title":"About"},"27":{"body":"This crate requires linking with FFmpeg, as detailed in the rusty_ffmpeg crate. We currently target FFmpeg 7.0.","breadcrumbs":"Tools » libvidformer » Building","id":"27","title":"Building"},"28":{"body":"For the vidformer builtin filters For the OpenCV/cv2 filters For using User Defined Filters (UDFs)","breadcrumbs":"Filters » Filters","id":"28","title":"Filters"},"29":{"body":"While most applications will use user-defined filters, vidformer ships with a handful of built-in filters to get you started:","breadcrumbs":"Filters » Built-in Filters » Built-in Filters","id":"29","title":"Built-in Filters"},"3":{"body":"🌐 Website 🚀 Getting Started 🐍 vidformer-py 🛠️ vidformer core","breadcrumbs":"Introduction » 📘 Documentation","id":"3","title":"📘 Documentation"},"30":{"body":"DrawText does exactly what it sounds like: draw text on a frame. For example: DrawText(frame, text=\"Hello, world!\", x=100, y=100, size=48, color=\"white\")","breadcrumbs":"Filters » Built-in Filters » DrawText","id":"30","title":"DrawText"},"31":{"body":"BoundingBox draws bounding boxes on a frame. For example: BoundingBox(frame, bounds=obj) Where obj is JSON with this schema: [ { \"class\": \"person\", \"confidence\": 0.916827917098999, \"x1\": 683.0721842447916, \"y1\": 100.92174338626751, \"x2\": 1006.863525390625, \"y2\": 720 }, { \"class\": \"dog\", \"confidence\": 0.902531921863556, \"x1\": 360.8750813802083, \"y1\": 47.983140622720974, \"x2\": 606.76171875, \"y2\": 717.9591837897462 }\n]","breadcrumbs":"Filters » Built-in Filters » BoundingBox","id":"31","title":"BoundingBox"},"32":{"body":"The Scale filter transforms one frame type to another. It changes both resolution and pixel format. This is the most important filter and is essential for building with vidformer. Arguments: Scale( frame: Frame, width: int = None, height: int = None, pix_fmt: str = None) By default missing width, height and format values are set to match frame. pix_fmt must match ffmpeg's name for a pixel format. For example: frame = Scale(frame, width=1280, height=720, pix_fmt=\"rgb24\")","breadcrumbs":"Filters » Built-in Filters » Scale","id":"32","title":"Scale"},"33":{"body":"IPC allows for calling User-Defined Filters (UDFs) running on the same system. It is an infrastructure-level filter and is used to implement other filters. It is configured with a socket and func, the filter's name, both strings. The IPC filter can not be directly invoked, rather IPC filters are constructed by a server upon request. This can be difficult, but vidformer-py handles this for you. As of right now IPC only supports rgb24 frames.","breadcrumbs":"Filters » Built-in Filters » IPC","id":"33","title":"IPC"},"34":{"body":"HStack & VStack allow for composing multiple frames together, stacking them either horizontally or vertically. It tries to automatically find a reasonable layout. Arguments: HStack( *frames: list[Frame], width: int, height: int, format: str) At least one frame is required, along with a width, height and format. For example: compilation = HStack(left_frame, right_frame, width=1280, height=720, format=\"rgb24\")","breadcrumbs":"Filters » Built-in Filters » HStack & VStack","id":"34","title":"HStack & VStack"},"35":{"body":"See vidformer.cv2 API docs . ⚠️ The cv2 module is a work in progress. If you find a bug or need a missing feature implemented feel free to file an issue or contribute yourself! Legend: ✅ - Support 🔸 - Support via OpenCV cv2 ❌ - Not yet implemented","breadcrumbs":"Filters » OpenCV/cv2 » OpenCV/cv2 Functions","id":"35","title":"OpenCV/cv2 Functions"},"36":{"body":"cv2.vidplay(video2) - Play a VideoWriter, Spec, or Source VideoWriter.spec() - Return the Spec of an output video Frame.numpy() - Return the frame as a numpy array cv2.setTo - The OpenCV Mat.setTo function (not in cv2)","breadcrumbs":"Filters » OpenCV/cv2 » Vidformer-specific Functions","id":"36","title":"Vidformer-specific Functions"},"37":{"body":"Class Status VideoCapture ✅ VideoWriter ✅ VideoWriter_fourcc ✅ Function Status imread ✅ imwrite ✅","breadcrumbs":"Filters » OpenCV/cv2 » opencv","id":"37","title":"opencv"},"38":{"body":"Drawing Functions: Function Status arrowedLine ✅ circle ✅ clipLine ❌ drawContours ❌ drawMarker ❌ ellipse ❌ ellipse2Poly ❌ fillConvexPoly ❌ fillPoly ❌ getFontScaleFromHeight 🔸 getTextSize 🔸 line ✅ polylines ❌ putText ✅ rectangle ✅","breadcrumbs":"Filters » OpenCV/cv2 » opencv.imgproc","id":"38","title":"opencv.imgproc"},"39":{"body":"Function Status addWeighted ✅","breadcrumbs":"Filters » OpenCV/cv2 » opencv.core","id":"39","title":"opencv.core"},"4":{"body":"Vidformer is a highly modular suite of tools that work together; these are detailed here . ❌ vidformer is NOT : A conventional video editor (like Premiere Pro or Final Cut) A video database/VDBMS A natural language query interface for video A computer vision library (like OpenCV) A computer vision AI model (like CLIP or Yolo) However, vidformer is highly complementary to each of these. If you're working on any of the later four, vidformer may be for you. File Layout : ./vidformer : The core transformation library ./vidformer-py : A Python video editing client ./vidformer-cli : A command-line interface for vidformer servers ./snake-pit : The main vidformer test suite ./docs : The vidformer website License: Vidformer is open source under Apache-2.0 . Contributions welcome.","breadcrumbs":"Introduction » 🔍 About the project","id":"4","title":"🔍 About the project"},"40":{"body":"To implement a new user-defined filter (UDF) you need to host a filter server over a UNIX Domain Socket. The vidformer-py library makes this easy. Filters take some combination of frames and data (string, int, bool) and return a single frame result. The vidformer project uses Python-style arguments, allowing ordered and named arguments (*args and **kwargs style). To do this we define a new filter class and host it: import vidformer as vf\nimport cv2 class MyFilter(vf.UDF): def filter(self, frame: vf.UDFFrame, name: str): \"\"\"Return the result frame.\"\"\" text = f\"Hello, {name}!\" image = frame.data().copy() cv2.putText( image, text, (100,100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 1, ) return vf.UDFFrame(image, frame.frame_type()) def filter_type(self, frame: vf.UDFFrameType, _name: str): \"\"\"Returns the type of the output frame.\"\"\" return frame mf_udf = MyFilter(\"MyFilter\") # name used for pretty printing my_filter = mf_udf.into_filter() # host the UDF in a subprocess, returns a vf.Filter Now we can use our newly-created filter in specs: my_filter(some_frame, \"vidformer\"). There is a catch, UDFs currently only support rgb24 pixel formats. So invoking my_filter will need to convert around this: scale = vf.Filter('Scale') def render(t, i): f = scale(tos[t], pix_fmt=\"rgb24\", width=1280, height=720) f = my_filter(f, \"world\") f = scale(f, pix_fmt=\"yuv420p\", width=1280, height=720) return f","breadcrumbs":"Filters » User-Defined Filters » User-Defined Filters","id":"40","title":"User-Defined Filters"},"41":{"body":"An unordered list of potential future features: Igni - A scale-out multi-tenant vidformer server in the cloud Supervision Integration Full GPU Acceleration WebAssembly Builds WebAssembly user defined filters & specs","breadcrumbs":"Roadmap » Roadmap","id":"41","title":"Roadmap"},"42":{"body":"","breadcrumbs":"FAQ » FAQ","id":"42","title":"FAQ"},"43":{"body":"In short, essentially everything. vidformer uses the FFmpeg/libav* libraries internally, so any media FFmpeg works with should work in vidformer as well. We support many container formats (e.g., mp4, mov) and codecs (e.g., H.264, VP8). A full list of supported codecs enabled in a vidformer build can be found by running: vidformer-cli codecs","breadcrumbs":"FAQ » What video formats does vidformer support?","id":"43","title":"What video formats does vidformer support?"},"44":{"body":"Yes, vidformer uses Apache OpenDAL for I/O, so most common data/storage access protocols are supported. However, not all storage services are enabled in distributed binaries. We guarantee that HTTP, S3, and the local filesystem always work.","breadcrumbs":"FAQ » Can I access remote videos on the internet?","id":"44","title":"Can I access remote videos on the internet?"},"45":{"body":"vidformer is far more expressive than the FFmpeg filter interface. Mainly, vidformer is designed for work around data, so edits are created programatically and edits can reference data. Also, vidformer enables serving resut videos on demand. vidformer uses the FFmpeg/libav* libraries internally, so any media FFmpeg works with should also work in vidformer.","breadcrumbs":"FAQ » How does vidformer compare to FFmpeg?","id":"45","title":"How does vidformer compare to FFmpeg?"},"46":{"body":"vidformer orchestrates data movment in video synthesis tasks, but does not implement image processing directly. Most use cases will still use OpenCV for this.","breadcrumbs":"FAQ » How does vidformer compare to OpenCV/cv2?","id":"46","title":"How does vidformer compare to OpenCV/cv2?"},"5":{"body":"Installation Getting started with the cv2 compatability layer Getting started with the core vidformer-py DSL","breadcrumbs":"Getting Started » Getting Started","id":"5","title":"Getting Started"},"6":{"body":"Using vidformer requires the Python client library, vidformer-py, and a yrden server which is distributed through vidformer-cli.","breadcrumbs":"Getting Started » Install » Install","id":"6","title":"Install"},"7":{"body":"pip install vidformer","breadcrumbs":"Getting Started » Install » vidformer-py","id":"7","title":"vidformer-py"},"8":{"body":"","breadcrumbs":"Getting Started » Install » vidformer-cli","id":"8","title":"vidformer-cli"},"9":{"body":"docker pull dominikwinecki/vidformer:latest\ndocker run --rm -it -p 8000:8000 dominikwinecki/vidformer:latest yrden --print-url This launches a vidformer yrden server, which is our reference server implementation for local usage, on port 8000. If you want to read or save video files locally add -v /my/local/dir:/data and then reference them as /data in the code. To use: import vidformer as vf\nserver = vf.YrdenServer(domain=\"localhost\", port=8000) # or for cv2\nimport vidformer.cv2 as cv2\ncv2.set_cv2_server(server)","breadcrumbs":"Getting Started » Install » 🐳 Docker:","id":"9","title":"🐳 Docker:"}},"length":47,"save":true},"fields":["title","body","breadcrumbs"],"index":{"body":{"root":{"0":{".":{"9":{"0":{"2":{"5":{"3":{"1":{"9":{"2":{"1":{"8":{"6":{"3":{"5":{"5":{"6":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"1":{"6":{"8":{"2":{"7":{"9":{"1":{"7":{"0":{"9":{"8":{"9":{"9":{"9":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":4,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}},"1":{"0":{"0":{",":{"1":{"0":{"0":{"df":1,"docs":{"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},".":{"9":{"2":{"1":{"7":{"4":{"3":{"3":{"8":{"6":{"2":{"6":{"7":{"5":{"1":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"6":{".":{"8":{"6":{"3":{"5":{"2":{"5":{"3":{"9":{"0":{"6":{"2":{"5":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":3,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}}},"8":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"2":{"8":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.0}}},"9":{"2":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":5,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}},"2":{".":{"0":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"4":{"df":2,"docs":{"18":{"tf":2.23606797749979},"20":{"tf":1.0}}},"5":{"5":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"3":{"0":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}},"6":{"0":{".":{"8":{"7":{"5":{"0":{"8":{"1":{"3":{"8":{"0":{"2":{"0":{"8":{"3":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"4":{"7":{".":{"9":{"8":{"3":{"1":{"4":{"0":{"6":{"2":{"2":{"7":{"2":{"0":{"9":{"7":{"4":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"5":{"0":{"0":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":2,"docs":{"18":{"tf":1.7320508075688772},"20":{"tf":1.0}},"x":{"5":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}},"6":{"0":{"6":{".":{"7":{"6":{"1":{"7":{"1":{"8":{"7":{"5":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"8":{"3":{".":{"0":{"7":{"2":{"1":{"8":{"4":{"2":{"4":{"4":{"7":{"9":{"1":{"6":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"7":{".":{"0":{"df":1,"docs":{"27":{"tf":1.0}}},"df":0,"docs":{}},"1":{"7":{".":{"9":{"5":{"9":{"1":{"8":{"3":{"7":{"8":{"9":{"7":{"4":{"6":{"2":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"2":{"0":{"df":2,"docs":{"18":{"tf":1.0},"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"8":{"0":{"0":{"0":{":":{"8":{"0":{"0":{"0":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.0}}},"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"40":{"tf":1.0}}}}},"df":0,"docs":{}}},"a":{"a":{"c":{"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}},"c":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"41":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}},"d":{"d":{"df":1,"docs":{"9":{"tf":1.0}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"39":{"tf":1.0}}}}}}}}},"df":1,"docs":{"12":{"tf":1.0}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"i":{"df":1,"docs":{"4":{"tf":1.0}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":7,"docs":{"1":{"tf":1.0},"2":{"tf":1.0},"22":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"33":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"34":{"tf":1.0}}}}},"w":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"44":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"d":{"6":{"4":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"23":{"tf":1.0},"32":{"tf":1.0}}}}}},"p":{"a":{"c":{"df":0,"docs":{},"h":{"df":3,"docs":{"26":{"tf":1.0},"4":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"35":{"tf":1.0}}},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"29":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"10":{"tf":1.0}}}},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"40":{"tf":1.0},"45":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"y":{"df":2,"docs":{"22":{"tf":2.23606797749979},"36":{"tf":1.0}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}}}}},"v":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":2,"docs":{"10":{"tf":1.0},"11":{"tf":1.0}}}}},"df":0,"docs":{}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.0}}}}},"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"10":{"tf":1.4142135623730951},"44":{"tf":1.0}}}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"b":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"40":{"tf":1.0}}}},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"32":{"tf":1.0},"33":{"tf":1.0}}}},"u":{"d":{"df":1,"docs":{"19":{"tf":1.0}}},"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"19":{"tf":1.0},"31":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"31":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"19":{"tf":1.0},"31":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}}},"s":{"=":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"o":{"b":{"df":0,"docs":{},"j":{"df":1,"docs":{"31":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"x":{"df":2,"docs":{"19":{"tf":1.4142135623730951},"31":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"k":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"u":{"df":0,"docs":{},"g":{"df":1,"docs":{"35":{"tf":1.0}}},"i":{"df":0,"docs":{},"l":{"d":{"df":8,"docs":{"11":{"tf":1.4142135623730951},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"27":{"tf":1.0},"32":{"tf":1.0},"41":{"tf":1.0},"43":{"tf":1.0}}},"df":0,"docs":{},"t":{"df":2,"docs":{"19":{"tf":1.0},"29":{"tf":1.4142135623730951}},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"28":{"tf":1.0}}}}}}},"n":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{}}}},"c":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"33":{"tf":1.0}}}},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"13":{"tf":1.0}}}},"df":0,"docs":{}},"p":{".":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"v":{"2":{".":{"c":{"a":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"p":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"o":{"df":1,"docs":{"11":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"18":{"tf":1.0},"46":{"tf":1.0}}}},"t":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"32":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}}},"i":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"l":{"df":1,"docs":{"38":{"tf":1.0}}}},"df":0,"docs":{}}},"l":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":3,"docs":{"31":{"tf":1.4142135623730951},"37":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"i":{"df":6,"docs":{"10":{"tf":2.449489742783178},"11":{"tf":1.0},"4":{"tf":1.0},"43":{"tf":1.0},"6":{"tf":1.0},"8":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"23":{"tf":2.449489742783178},"4":{"tf":1.0},"6":{"tf":1.0}}}}},"p":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":5,"docs":{"18":{"tf":1.0},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"21":{"tf":1.0},"4":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"o":{"df":0,"docs":{},"u":{"d":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"o":{"d":{"df":0,"docs":{},"e":{"c":{"df":1,"docs":{"43":{"tf":1.7320508075688772}}},"df":6,"docs":{"1":{"tf":1.0},"18":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":1.0},"25":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{},"l":{"a":{"b":{"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.7320508075688772},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}},"o":{"df":0,"docs":{},"r":{"=":{"\"":{"df":0,"docs":{},"w":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"30":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}},"s":{".":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"m":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"18":{"tf":1.0},"40":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"44":{"tf":1.0}}}}},"p":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"45":{"tf":1.0},"46":{"tf":1.0}}},"t":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":2,"docs":{"11":{"tf":1.0},"34":{"tf":1.0}}}},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}}}}},"o":{"df":0,"docs":{},"s":{"df":1,"docs":{"34":{"tf":1.0}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"20":{"tf":1.0},"22":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}}},"n":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"33":{"tf":1.0}}}}}}},"n":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.0},"22":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":4,"docs":{"18":{"tf":1.0},"22":{"tf":1.7320508075688772},"23":{"tf":1.0},"33":{"tf":1.0}}}},"df":0,"docs":{}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"43":{"tf":1.0}}}},"n":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"23":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"25":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"4":{"tf":1.0}}}},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"14":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"df":7,"docs":{"11":{"tf":1.0},"16":{"tf":1.0},"23":{"tf":1.0},"25":{"tf":1.0},"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}}}}}}}},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"27":{"tf":1.4142135623730951}},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":2,"docs":{"0":{"tf":1.0},"25":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":5,"docs":{"1":{"tf":1.0},"18":{"tf":2.23606797749979},"23":{"tf":1.0},"40":{"tf":1.0},"45":{"tf":1.0}},"e":{"_":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":1,"docs":{"14":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"27":{"tf":1.0},"40":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"21":{"tf":1.0}}}}}},"t":{"df":1,"docs":{"4":{"tf":1.0}}}},"v":{"2":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"40":{"tf":1.0}}}}}}}}}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}}}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":1,"docs":{"40":{"tf":1.0}}}}}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"v":{"2":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":1,"docs":{"9":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"36":{"tf":1.0}}}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":2,"docs":{"14":{"tf":1.0},"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"14":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"15":{"tf":1.0}}}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"c":{"(":{"*":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":0,"docs":{},"v":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"2":{"df":1,"docs":{"36":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":1.0},"15":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":10,"docs":{"1":{"tf":1.0},"12":{"tf":2.0},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"2":{"tf":2.0},"35":{"tf":1.4142135623730951},"36":{"tf":1.0},"40":{"tf":1.0},"5":{"tf":1.0},"9":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"44":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"b":{"a":{"df":0,"docs":{},"s":{"df":2,"docs":{"1":{"tf":1.0},"22":{"tf":1.0}},"e":{"/":{"df":0,"docs":{},"v":{"d":{"b":{"df":0,"docs":{},"m":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":11,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.0},"19":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":2.8284271247461903},"23":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"40":{"tf":1.0},"45":{"tf":1.4142135623730951},"46":{"tf":1.0},"9":{"tf":1.0}},"—":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"df":2,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"d":{"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}},"f":{"a":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"32":{"tf":1.0}}}}}},"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"40":{"tf":1.7320508075688772}},"i":{"df":0,"docs":{},"n":{"df":7,"docs":{"18":{"tf":1.0},"21":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.7320508075688772},"41":{"tf":1.0}}}}},"m":{"a":{"df":0,"docs":{},"n":{"d":{"df":4,"docs":{"1":{"tf":1.0},"15":{"tf":1.0},"23":{"tf":1.4142135623730951},"45":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"y":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.0},"45":{"tf":1.0}}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":4,"docs":{"11":{"tf":1.0},"2":{"tf":1.0},"27":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}},"v":{"df":1,"docs":{"10":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"33":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":3,"docs":{"22":{"tf":1.0},"33":{"tf":1.0},"46":{"tf":1.0}}}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":1.0},"15":{"tf":1.4142135623730951}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"15":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"44":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"o":{"c":{"df":2,"docs":{"35":{"tf":1.0},"4":{"tf":1.0}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"9":{"tf":1.7320508075688772}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"24":{"tf":1.4142135623730951},"25":{"tf":1.0},"3":{"tf":1.0}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}},"g":{"df":1,"docs":{"31":{"tf":1.0}}},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":5,"docs":{"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"i":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{":":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"r":{"a":{"df":0,"docs":{},"w":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}},"df":4,"docs":{"22":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0}},"m":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"38":{"tf":1.0}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"30":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"22":{"tf":1.0},"30":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"l":{"df":2,"docs":{"16":{"tf":1.4142135623730951},"5":{"tf":1.0}}}},"u":{"df":0,"docs":{},"e":{"df":1,"docs":{"13":{"tf":1.0}}}}},"df":0,"docs":{},"e":{".":{"df":0,"docs":{},"g":{"df":1,"docs":{"43":{"tf":1.4142135623730951}}}},"a":{"c":{"df":0,"docs":{},"h":{"df":3,"docs":{"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"4":{"tf":1.0}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"40":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"2":{"tf":1.0}}}}}}}},"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":4,"docs":{"1":{"tf":1.0},"23":{"tf":1.0},"4":{"tf":1.0},"45":{"tf":1.4142135623730951}},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"i":{"df":2,"docs":{"1":{"tf":1.0},"22":{"tf":1.0}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{"df":1,"docs":{"38":{"tf":1.0}},"e":{"2":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"m":{"b":{"df":0,"docs":{},"e":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"n":{"a":{"b":{"df":0,"docs":{},"l":{"df":4,"docs":{"1":{"tf":1.4142135623730951},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"d":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"32":{"tf":1.0},"43":{"tf":1.0}}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"43":{"tf":1.0}}}}}}}},"x":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"30":{"tf":1.0}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":9,"docs":{"10":{"tf":1.0},"14":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"22":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"24":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":2,"docs":{"10":{"tf":1.0},"24":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"45":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"f":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"a":{"c":{"df":0,"docs":{},"e":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{}},"q":{"df":1,"docs":{"42":{"tf":1.0}}},"r":{"df":1,"docs":{"45":{"tf":1.0}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"1":{"tf":1.0},"23":{"tf":1.0}}}}}}},"df":1,"docs":{"40":{"tf":2.0}},"e":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":2,"docs":{"35":{"tf":1.0},"41":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"35":{"tf":1.0}}}},"w":{"df":2,"docs":{"18":{"tf":1.0},"23":{"tf":1.0}}}},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"'":{"df":1,"docs":{"32":{"tf":1.0}}},"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"b":{"a":{"df":0,"docs":{},"v":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":5,"docs":{"11":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.4142135623730951},"43":{"tf":1.0},"45":{"tf":1.7320508075688772}}}}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":4,"docs":{"26":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.0},"9":{"tf":1.0}},"s":{"df":0,"docs":{},"y":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"44":{"tf":1.0}}}}}}}}},"l":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"'":{"df":1,"docs":{"33":{"tf":1.0}}},"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":13,"docs":{"12":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.4142135623730951},"22":{"tf":1.7320508075688772},"26":{"tf":1.0},"28":{"tf":2.0},"29":{"tf":1.7320508075688772},"32":{"tf":1.4142135623730951},"33":{"tf":2.23606797749979},"40":{"tf":2.449489742783178},"41":{"tf":1.0},"45":{"tf":1.0}}}}}},"n":{"a":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}},"df":1,"docs":{"4":{"tf":1.0}}}},"d":{"df":3,"docs":{"2":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"18":{"tf":1.0}}}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"d":{"=":{"'":{"<":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":1,"docs":{"24":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"=":{"'":{"_":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"_":{"_":{"df":1,"docs":{"24":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":1,"docs":{"24":{"tf":1.0}}}},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"25":{"tf":1.0}}}}},"m":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"o":{"c":{"df":0,"docs":{},"u":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"b":{"2":{"4":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}}},"df":7,"docs":{"1":{"tf":1.0},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"32":{"tf":1.7320508075688772},"34":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"p":{"df":4,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"1":{"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"5":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"20":{"tf":1.0}}}},"df":1,"docs":{"18":{"tf":1.7320508075688772}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{".":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"(":{")":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"36":{"tf":1.0}}}}}}}},"df":14,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":3.1622776601683795},"19":{"tf":1.0},"2":{"tf":1.0},"20":{"tf":1.7320508075688772},"22":{"tf":2.8284271247461903},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":2.23606797749979},"33":{"tf":1.0},"34":{"tf":1.7320508075688772},"36":{"tf":1.0},"40":{"tf":2.6457513110645907}},"r":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"35":{"tf":1.0}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":2,"docs":{"41":{"tf":1.0},"43":{"tf":1.0}}}},"n":{"c":{"df":1,"docs":{"33":{"tf":1.0}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":9,"docs":{"12":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"22":{"tf":2.0},"35":{"tf":1.0},"36":{"tf":1.4142135623730951},"37":{"tf":1.0},"38":{"tf":1.4142135623730951},"39":{"tf":1.0}}}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"41":{"tf":1.0}}}}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":6,"docs":{"12":{"tf":1.4142135623730951},"16":{"tf":1.4142135623730951},"2":{"tf":1.0},"24":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":1.7320508075688772}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"11":{"tf":1.0}}}},"p":{"df":0,"docs":{},"u":{"df":1,"docs":{"41":{"tf":1.0}}}},"r":{"a":{"df":0,"docs":{},"y":{"8":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"d":{".":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"h":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"*":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"u":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"44":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"d":{"df":4,"docs":{"13":{"tf":1.0},"17":{"tf":1.0},"2":{"tf":1.0},"24":{"tf":1.0}}},"df":0,"docs":{}}}},"h":{".":{"2":{"6":{"4":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"29":{"tf":1.0}},"l":{"df":2,"docs":{"25":{"tf":1.0},"33":{"tf":1.0}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"e":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":1,"docs":{"20":{"tf":1.7320508075688772}},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"=":{"7":{"2":{"0":{"df":4,"docs":{"20":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"/":{"/":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.0}}}}}}}}},"df":7,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"2":{"tf":1.4142135623730951},"20":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951}}}}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":4,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.0},"18":{"tf":1.0},"2":{"tf":1.0}}}},"p":{"df":1,"docs":{"18":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"'":{"df":1,"docs":{"14":{"tf":1.0}}},"df":3,"docs":{"11":{"tf":1.0},"18":{"tf":1.7320508075688772},"4":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.4142135623730951}}}}}}},"l":{"df":1,"docs":{"23":{"tf":1.0}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"34":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.7320508075688772}}}}},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"20":{"tf":1.0},"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"20":{"tf":1.4142135623730951},"34":{"tf":1.7320508075688772}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":1,"docs":{"44":{"tf":1.0}},"s":{":":{"/":{"/":{"df":0,"docs":{},"f":{".":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{".":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"d":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"2":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":2,"docs":{"14":{"tf":1.0},"18":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"u":{"b":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"/":{"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":0,"docs":{},"l":{"a":{"b":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"/":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"/":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"/":{"<":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{">":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"u":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}}}},"i":{".":{"df":2,"docs":{"18":{"tf":1.0},"23":{"tf":1.0}}},"/":{"df":0,"docs":{},"o":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}}}}},"m":{"a":{"df":0,"docs":{},"g":{"df":3,"docs":{"22":{"tf":1.0},"40":{"tf":1.4142135623730951},"46":{"tf":1.0}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":8,"docs":{"12":{"tf":1.0},"23":{"tf":1.0},"26":{"tf":1.0},"33":{"tf":1.0},"35":{"tf":1.4142135623730951},"40":{"tf":1.0},"46":{"tf":1.0},"9":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":9,"docs":{"10":{"tf":1.4142135623730951},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"2":{"tf":1.7320508075688772},"32":{"tf":1.0},"40":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"37":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"37":{"tf":1.0}}}}}}},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":3,"docs":{"18":{"tf":1.7320508075688772},"20":{"tf":1.4142135623730951},"22":{"tf":1.0}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}},"r":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":3,"docs":{"0":{"tf":1.0},"23":{"tf":1.0},"33":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"l":{"df":6,"docs":{"10":{"tf":1.0},"13":{"tf":1.4142135623730951},"17":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}}},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"n":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"a":{"d":{"df":2,"docs":{"15":{"tf":1.0},"18":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"t":{"(":{"c":{"a":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"v":{"2":{".":{"c":{"a":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}}}}},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":4,"docs":{"18":{"tf":1.0},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951},"40":{"tf":1.0}},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"18":{"tf":1.0}},"r":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"f":{"a":{"c":{"df":5,"docs":{"0":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"4":{"tf":1.4142135623730951},"45":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"n":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.0}}}}}}},"r":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"p":{"c":{"df":1,"docs":{"33":{"tf":2.23606797749979}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"35":{"tf":1.0}}}}},"t":{"'":{"df":3,"docs":{"18":{"tf":1.0},"23":{"tf":1.0},"26":{"tf":1.0}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":2,"docs":{"11":{"tf":1.0},"22":{"tf":1.0}}}}}}}},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"(":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":3,"docs":{"19":{"tf":1.0},"23":{"tf":1.0},"31":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951}}}}}}},"k":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}}}}},"df":0,"docs":{}}},"l":{"a":{"b":{"df":1,"docs":{"0":{"tf":1.0}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"u":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"23":{"tf":2.0},"4":{"tf":1.0}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"22":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"20":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"22":{"tf":1.0},"34":{"tf":1.0},"4":{"tf":1.0}}}}}},"z":{"df":0,"docs":{},"y":{"/":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"35":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"'":{"df":1,"docs":{"19":{"tf":1.0}}},"df":1,"docs":{"18":{"tf":1.4142135623730951}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"23":{"tf":1.0},"33":{"tf":1.0}}}}}},"i":{"b":{")":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"25":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"a":{"df":0,"docs":{},"v":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{},"f":{"d":{"df":0,"docs":{},"k":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"v":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}}}}},"r":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":9,"docs":{"11":{"tf":1.0},"23":{"tf":2.449489742783178},"25":{"tf":1.4142135623730951},"26":{"tf":1.0},"4":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":1.0},"45":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":4,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"4":{"tf":1.0}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":3,"docs":{"23":{"tf":1.0},"38":{"tf":1.0},"4":{"tf":1.0}}},"k":{"df":5,"docs":{"11":{"tf":1.0},"15":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"27":{"tf":1.0}}}},"s":{"df":0,"docs":{},"t":{"[":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"41":{"tf":1.0},"43":{"tf":1.0}}}}},"o":{"a":{"d":{"df":2,"docs":{"19":{"tf":1.4142135623730951},"22":{"tf":1.0}}},"df":0,"docs":{}},"c":{"a":{"df":0,"docs":{},"l":{"df":3,"docs":{"23":{"tf":1.0},"44":{"tf":1.0},"9":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.0}}}}},"m":{"a":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"45":{"tf":1.0}}}}}},"k":{"df":0,"docs":{},"e":{"df":1,"docs":{"40":{"tf":1.0}}}},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"43":{"tf":1.0}}}},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"18":{"tf":1.0}}}},"t":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"36":{"tf":1.0}}}}}}}},"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"18":{"tf":1.0},"32":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"i":{"a":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"d":{"=":{"\"":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"k":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"f":{"_":{"df":0,"docs":{},"u":{"d":{"df":0,"docs":{},"f":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"d":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"32":{"tf":1.0},"35":{"tf":1.0}}}}},"o":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"22":{"tf":1.7320508075688772},"4":{"tf":1.0}}}},"u":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}},"df":1,"docs":{"35":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":1,"docs":{"45":{"tf":1.0}}}},"v":{"df":1,"docs":{"43":{"tf":1.0}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"25":{"tf":1.0}}}}}}},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"46":{"tf":1.0}}}}}}}},"p":{"4":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}},"m":{"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"i":{"a":{"df":1,"docs":{"26":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}},"p":{"df":0,"docs":{},"l":{"df":2,"docs":{"18":{"tf":1.0},"34":{"tf":1.0}}}}}}}},"v":{"df":1,"docs":{"10":{"tf":1.0}}},"y":{"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"/":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{":":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"v":{"df":0,"docs":{},"f":{".":{"df":0,"docs":{},"u":{"d":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}}},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":4,"docs":{"18":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":2.0}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}},"e":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"d":{"df":4,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0},"35":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"13":{"tf":1.0}}}}}}},"w":{"df":1,"docs":{"40":{"tf":1.4142135623730951}},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"40":{"tf":1.0}}}}},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"25":{"tf":1.0}},"e":{"df":2,"docs":{"15":{"tf":1.0},"32":{"tf":1.7320508075688772}}}},"t":{"df":0,"docs":{},"e":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":3,"docs":{"15":{"tf":1.7320508075688772},"18":{"tf":1.0},"21":{"tf":1.0}}}}}},"df":2,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0}}}},"w":{"df":4,"docs":{"18":{"tf":2.0},"19":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.0}}}},"u":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"36":{"tf":1.0}}}}}}},"o":{"b":{"df":0,"docs":{},"j":{"df":1,"docs":{"31":{"tf":1.0}},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":1,"docs":{"14":{"tf":1.0}},"n":{"df":2,"docs":{"32":{"tf":1.0},"34":{"tf":1.0}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"v":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"39":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"g":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"c":{"df":1,"docs":{"38":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"/":{"c":{"df":0,"docs":{},"v":{"2":{"df":3,"docs":{"28":{"tf":1.0},"35":{"tf":1.0},"46":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":9,"docs":{"11":{"tf":1.0},"12":{"tf":1.0},"2":{"tf":1.0},"26":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.0},"4":{"tf":1.0},"46":{"tf":1.0}}}},"d":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}},"df":4,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"2":{"tf":1.0},"4":{"tf":1.0}}}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":1,"docs":{"22":{"tf":1.0}}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.7320508075688772}}}}}},"r":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":1,"docs":{"46":{"tf":1.0}}}}}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"18":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"0":{"tf":1.0}}}},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"14":{"tf":1.0}}},"t":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":5,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"23":{"tf":1.4142135623730951},"41":{"tf":1.0}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":5,"docs":{"18":{"tf":2.0},"19":{"tf":1.0},"22":{"tf":1.0},"36":{"tf":1.0},"40":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"19":{"tf":1.0},"20":{"tf":1.0},"23":{"tf":1.0},"40":{"tf":1.0}},"l":{"a":{"df":0,"docs":{},"y":{"df":2,"docs":{"19":{"tf":1.0},"21":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":1,"docs":{"12":{"tf":1.0}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}}},"r":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"15":{"tf":1.0}}}}},"df":1,"docs":{"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"31":{"tf":1.0}}}}}}},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"7":{"tf":1.0}},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"t":{"df":1,"docs":{"4":{"tf":1.0}}},"x":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"b":{"2":{"4":{"df":2,"docs":{"32":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":3,"docs":{"18":{"tf":1.0},"20":{"tf":1.0},"32":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":3,"docs":{"22":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}}},"l":{"a":{"c":{"df":0,"docs":{},"e":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"23":{"tf":1.0}}}},"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}},"y":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":6,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":2.6457513110645907},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"36":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"r":{"df":0,"docs":{},"t":{"=":{"8":{"0":{"0":{"0":{"df":2,"docs":{"18":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"41":{"tf":1.0}}}}}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":2,"docs":{"1":{"tf":1.0},"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"40":{"tf":1.0}}}}}},"i":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}}},"df":3,"docs":{"18":{"tf":1.4142135623730951},"40":{"tf":1.0},"9":{"tf":1.0}}}}},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":5,"docs":{"1":{"tf":1.0},"23":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"46":{"tf":1.0}}}}}},"df":1,"docs":{"4":{"tf":1.0}},"g":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"45":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":3,"docs":{"12":{"tf":1.0},"23":{"tf":1.0},"35":{"tf":1.0}}}}}}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":4,"docs":{"0":{"tf":1.0},"23":{"tf":1.4142135623730951},"4":{"tf":1.0},"40":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"44":{"tf":1.0}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"0":{"tf":1.0},"23":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":1,"docs":{"24":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"9":{"tf":1.0}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}},"y":{"df":10,"docs":{"16":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":1.7320508075688772},"3":{"tf":1.0},"33":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.0}},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"0":{"tf":1.0},"24":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":6,"docs":{"2":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"1":{"tf":1.0},"4":{"tf":1.0}}}}},"i":{"c":{"df":0,"docs":{},"k":{"df":3,"docs":{"2":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0}}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"(":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"2":{"4":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.0}}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"22":{"tf":1.0}}}}}}},"df":1,"docs":{"19":{"tf":1.0}},"e":{"a":{"d":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":1,"docs":{"23":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"34":{"tf":1.0}}}}}},"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"18":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":1,"docs":{"38":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":3,"docs":{"23":{"tf":1.0},"45":{"tf":1.0},"9":{"tf":1.4142135623730951}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"l":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.0}}}}},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"40":{"tf":1.0}}}},"df":5,"docs":{"15":{"tf":1.0},"18":{"tf":2.0},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"l":{"a":{"c":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":1,"docs":{"11":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":3,"docs":{"1":{"tf":1.0},"22":{"tf":2.0},"23":{"tf":1.0}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"33":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"r":{"df":4,"docs":{"11":{"tf":1.0},"27":{"tf":1.0},"34":{"tf":1.0},"6":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"22":{"tf":1.0},"32":{"tf":1.0}}}}}},"t":{"df":1,"docs":{"23":{"tf":1.0}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":10,"docs":{"1":{"tf":1.4142135623730951},"13":{"tf":1.0},"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}}},"t":{"df":1,"docs":{"45":{"tf":1.0}}}}},"t":{"df":3,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"1":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":7,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"22":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"40":{"tf":2.6457513110645907}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"g":{"b":{"2":{"4":{"df":3,"docs":{"22":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"20":{"tf":1.0},"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":1,"docs":{"33":{"tf":1.0}}}}}},"m":{"df":1,"docs":{"9":{"tf":1.0}}},"o":{"a":{"d":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"p":{"df":1,"docs":{"41":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"u":{"df":0,"docs":{},"n":{"df":4,"docs":{"15":{"tf":1.0},"33":{"tf":1.0},"43":{"tf":1.0},"9":{"tf":1.0}}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.0},"26":{"tf":1.0}},"y":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"27":{"tf":1.0}}}}}}}}},"df":0,"docs":{}}}}}},"s":{"3":{"df":1,"docs":{"44":{"tf":1.0}}},"a":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":1,"docs":{"26":{"tf":1.0}}}},"m":{"df":0,"docs":{},"e":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"33":{"tf":1.0}}},"p":{"df":0,"docs":{},"l":{"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"e":{"df":4,"docs":{"13":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"9":{"tf":1.0}}}}},"c":{"a":{"df":0,"docs":{},"l":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"32":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"[":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}}},"df":4,"docs":{"23":{"tf":1.4142135623730951},"32":{"tf":1.7320508075688772},"40":{"tf":1.0},"41":{"tf":1.0}}}}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"a":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"2":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":4,"docs":{"12":{"tf":1.0},"13":{"tf":1.0},"17":{"tf":1.0},"35":{"tf":1.0}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}}}},"r":{"df":0,"docs":{},"v":{"df":2,"docs":{"23":{"tf":1.0},"45":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":9,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.7320508075688772},"23":{"tf":2.6457513110645907},"33":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":1.7320508075688772}}}},"i":{"c":{"df":3,"docs":{"23":{"tf":1.0},"26":{"tf":1.0},"44":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"32":{"tf":1.0}}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"29":{"tf":1.0}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"43":{"tf":1.0}}}},"w":{"df":1,"docs":{"21":{"tf":1.0}}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"22":{"tf":1.0},"23":{"tf":1.0},"40":{"tf":1.0}}}}},"z":{"df":0,"docs":{},"e":{"=":{"4":{"8":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"k":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"15":{"tf":1.0}}}}},"n":{"a":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"r":{"c":{"df":7,"docs":{"11":{"tf":1.0},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"36":{"tf":1.0},"4":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"'":{"df":1,"docs":{"22":{"tf":1.4142135623730951}}},".":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":7,"docs":{"18":{"tf":1.7320508075688772},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":2.0},"36":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0}},"i":{"df":0,"docs":{},"f":{"df":3,"docs":{"1":{"tf":1.7320508075688772},"23":{"tf":1.0},"36":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}}}},"q":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{},"n":{"d":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"t":{"df":10,"docs":{"12":{"tf":1.4142135623730951},"15":{"tf":1.0},"16":{"tf":1.4142135623730951},"18":{"tf":1.7320508075688772},"2":{"tf":1.7320508075688772},"23":{"tf":1.0},"24":{"tf":1.0},"29":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":1.7320508075688772}}}},"t":{"df":0,"docs":{},"u":{"df":3,"docs":{"37":{"tf":1.4142135623730951},"38":{"tf":1.0},"39":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"46":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{}}},"r":{"df":3,"docs":{"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}},"e":{"a":{"df":0,"docs":{},"m":{"/":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"13":{"tf":1.0}}}},"df":0,"docs":{}}}},"=":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"23":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"26":{"tf":1.0}}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":2,"docs":{"23":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}}},"u":{"b":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}}}}},"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"22":{"tf":1.7320508075688772}}}},"d":{"df":0,"docs":{},"o":{"df":1,"docs":{"10":{"tf":1.7320508075688772}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.4142135623730951}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":1,"docs":{"41":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":5,"docs":{"33":{"tf":1.0},"35":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":1.7320508075688772},"44":{"tf":1.0}}}}}}}},"y":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":2,"docs":{"22":{"tf":1.0},"23":{"tf":1.0}}}}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":3,"docs":{"22":{"tf":1.0},"23":{"tf":1.0},"46":{"tf":1.0}},"s":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"25":{"tf":1.0}}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":3,"docs":{"0":{"tf":1.0},"23":{"tf":1.7320508075688772},"33":{"tf":1.0}}}}}}}},"t":{"a":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":3,"docs":{"18":{"tf":1.0},"22":{"tf":1.0},"40":{"tf":1.0}}}},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"27":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"k":{"df":2,"docs":{"22":{"tf":1.0},"46":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"21":{"tf":1.0}}}}}}}}},"n":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"41":{"tf":1.0}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}},"x":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"30":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":3,"docs":{"22":{"tf":1.0},"30":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"20":{"tf":1.0}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":1,"docs":{"6":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":3,"docs":{"18":{"tf":1.7320508075688772},"19":{"tf":1.0},"22":{"tf":1.7320508075688772}}}}},"df":0,"docs":{}}}}}},"o":{"df":1,"docs":{"18":{"tf":1.0}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"23":{"tf":1.0},"34":{"tf":1.0},"4":{"tf":1.0}}}}}},"o":{"df":0,"docs":{},"l":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"4":{"tf":1.0}}}},"s":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.4142135623730951},"19":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"[":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.0},"19":{"tf":1.0}}}},"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":6,"docs":{"0":{"tf":1.0},"1":{"tf":1.4142135623730951},"23":{"tf":1.0},"25":{"tf":1.0},"32":{"tf":1.0},"4":{"tf":1.0}}}}}},"p":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"1":{"tf":1.0},"23":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":1,"docs":{"1":{"tf":1.0}}}}}}}},"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"34":{"tf":1.0}}},"u":{"df":0,"docs":{},"e":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"y":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":3,"docs":{"22":{"tf":1.0},"32":{"tf":1.0},"40":{"tf":1.0}}}}}},"u":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"2":{"2":{".":{"0":{"4":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"d":{"df":0,"docs":{},"f":{"df":3,"docs":{"28":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.7320508075688772}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":1,"docs":{"40":{"tf":1.0}}}},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":1,"docs":{"23":{"tf":1.0}},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"33":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"l":{"df":1,"docs":{"9":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"b":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"(":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{":":{"/":{"/":{"df":0,"docs":{},"f":{".":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{".":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"d":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"2":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":1,"docs":{"19":{"tf":1.0}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"s":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":20,"docs":{"1":{"tf":1.0},"10":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":2.23606797749979},"2":{"tf":1.0},"22":{"tf":1.4142135623730951},"23":{"tf":2.8284271247461903},"24":{"tf":1.0},"26":{"tf":1.7320508075688772},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.7320508075688772},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.4142135623730951},"6":{"tf":1.0},"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":6,"docs":{"21":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.0}}}},"r":{"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"/":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"v":{"2":{"df":0,"docs":{},"v":{"df":1,"docs":{"22":{"tf":1.0}}}},"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":1,"docs":{"32":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"b":{"df":0,"docs":{},"m":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":3,"docs":{"0":{"tf":1.4142135623730951},"24":{"tf":1.0},"25":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}}}}},"f":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"df":1,"docs":{"19":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"h":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"'":{"df":0,"docs":{},"s":{"c":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"(":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"u":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"40":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"y":{"df":0,"docs":{},"r":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":1,"docs":{"10":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"\"":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"\"":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"'":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}}}},"df":4,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.0},"40":{"tf":1.0},"9":{"tf":1.0}},"r":{"df":1,"docs":{"18":{"tf":1.0}}}},"i":{"a":{"df":2,"docs":{"23":{"tf":1.0},"35":{"tf":1.0}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"'":{"df":1,"docs":{"18":{"tf":1.0}}},"c":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"37":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":19,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":2.0},"14":{"tf":1.0},"15":{"tf":2.0},"18":{"tf":3.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.7320508075688772},"23":{"tf":2.8284271247461903},"25":{"tf":2.0},"26":{"tf":1.4142135623730951},"36":{"tf":1.0},"4":{"tf":2.0},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.0},"9":{"tf":1.0}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"36":{"tf":1.0},"37":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":1,"docs":{"36":{"tf":1.0}}},"df":0,"docs":{}}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"c":{"df":1,"docs":{"37":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":30,"docs":{"0":{"tf":1.0},"1":{"tf":2.0},"10":{"tf":2.0},"11":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":1.0},"16":{"tf":1.0},"18":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":2.8284271247461903},"24":{"tf":2.0},"25":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"3":{"tf":1.4142135623730951},"32":{"tf":1.0},"33":{"tf":1.0},"36":{"tf":1.0},"4":{"tf":3.3166247903554},"40":{"tf":2.0},"41":{"tf":1.0},"43":{"tf":2.23606797749979},"44":{"tf":1.0},"45":{"tf":2.449489742783178},"46":{"tf":1.4142135623730951},"5":{"tf":1.0},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951},"8":{"tf":1.0},"9":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"r":{"'":{"df":1,"docs":{"2":{"tf":1.0}}},".":{"c":{"df":0,"docs":{},"v":{"2":{"df":6,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.0},"2":{"tf":1.4142135623730951},"24":{"tf":1.0},"35":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"_":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"'":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.0}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"o":{"d":{"df":1,"docs":{"23":{"tf":2.23606797749979}}},"df":0,"docs":{}},"p":{"8":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":1,"docs":{"18":{"tf":1.0}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"*":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":2,"docs":{"20":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"w":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"k":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":2,"docs":{"12":{"tf":1.0},"16":{"tf":1.0}}}}}}}}}}},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"18":{"tf":1.0},"23":{"tf":1.7320508075688772},"9":{"tf":1.0}}}},"y":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":1,"docs":{"20":{"tf":1.7320508075688772}},"e":{"b":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"41":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"3":{"tf":1.0},"4":{"tf":1.0}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"l":{"df":2,"docs":{"18":{"tf":1.0},"43":{"tf":1.0}}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"10":{"tf":1.0}}}}},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"=":{"1":{"2":{"8":{"0":{"df":4,"docs":{"20":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}}},"df":7,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"2":{"tf":1.4142135623730951},"20":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.0}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"k":{"df":11,"docs":{"12":{"tf":1.0},"13":{"tf":1.4142135623730951},"15":{"tf":1.0},"18":{"tf":1.7320508075688772},"23":{"tf":1.4142135623730951},"26":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.4142135623730951},"43":{"tf":1.4142135623730951},"44":{"tf":1.0},"45":{"tf":1.7320508075688772}},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}}}},"l":{"d":{"df":6,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.0},"18":{"tf":1.0},"2":{"tf":1.0},"30":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"15":{"tf":1.0},"23":{"tf":1.4142135623730951}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"26":{"tf":1.0}}}}}}}}},"x":{"1":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"2":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"=":{"1":{"0":{"0":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"10":{"tf":1.0}}},"y":{"1":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"2":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"=":{"1":{"0":{"0":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"10":{"tf":1.0}},"e":{"df":1,"docs":{"44":{"tf":1.0}}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"4":{"tf":1.0}}}},"u":{"'":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"35":{"tf":1.0}}}}}}}}},"r":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":3,"docs":{"23":{"tf":2.23606797749979},"6":{"tf":1.0},"9":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":3,"docs":{"18":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"breadcrumbs":{"root":{"0":{".":{"9":{"0":{"2":{"5":{"3":{"1":{"9":{"2":{"1":{"8":{"6":{"3":{"5":{"5":{"6":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"1":{"6":{"8":{"2":{"7":{"9":{"1":{"7":{"0":{"9":{"8":{"9":{"9":{"9":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":4,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}},"1":{"0":{"0":{",":{"1":{"0":{"0":{"df":1,"docs":{"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},".":{"9":{"2":{"1":{"7":{"4":{"3":{"3":{"8":{"6":{"2":{"6":{"7":{"5":{"1":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"6":{".":{"8":{"6":{"3":{"5":{"2":{"5":{"3":{"9":{"0":{"6":{"2":{"5":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":3,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}}},"8":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"2":{"8":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.0}}},"9":{"2":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":5,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}},"2":{".":{"0":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}},"4":{"df":2,"docs":{"18":{"tf":2.23606797749979},"20":{"tf":1.0}}},"5":{"5":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"3":{"0":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}},"6":{"0":{".":{"8":{"7":{"5":{"0":{"8":{"1":{"3":{"8":{"0":{"2":{"0":{"8":{"3":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"4":{"7":{".":{"9":{"8":{"3":{"1":{"4":{"0":{"6":{"2":{"2":{"7":{"2":{"0":{"9":{"7":{"4":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"5":{"0":{"0":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":2,"docs":{"18":{"tf":1.7320508075688772},"20":{"tf":1.0}},"x":{"5":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}},"6":{"0":{"6":{".":{"7":{"6":{"1":{"7":{"1":{"8":{"7":{"5":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"8":{"3":{".":{"0":{"7":{"2":{"1":{"8":{"4":{"2":{"4":{"4":{"7":{"9":{"1":{"6":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"7":{".":{"0":{"df":1,"docs":{"27":{"tf":1.0}}},"df":0,"docs":{}},"1":{"7":{".":{"9":{"5":{"9":{"1":{"8":{"3":{"7":{"8":{"9":{"7":{"4":{"6":{"2":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"2":{"0":{"df":2,"docs":{"18":{"tf":1.0},"31":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"8":{"0":{"0":{"0":{":":{"8":{"0":{"0":{"0":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"18":{"tf":1.0}}},"_":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"40":{"tf":1.0}}}}},"df":0,"docs":{}}},"a":{"a":{"c":{"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}},"c":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"41":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.7320508075688772}}}}}},"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}},"d":{"d":{"df":1,"docs":{"9":{"tf":1.0}},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"39":{"tf":1.0}}}}}}}}},"df":1,"docs":{"12":{"tf":1.0}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"i":{"df":1,"docs":{"4":{"tf":1.0}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":7,"docs":{"1":{"tf":1.0},"2":{"tf":1.0},"22":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"33":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"34":{"tf":1.0}}}}},"w":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"44":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"d":{"6":{"4":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"23":{"tf":1.0},"32":{"tf":1.0}}}}}},"p":{"a":{"c":{"df":0,"docs":{},"h":{"df":3,"docs":{"26":{"tf":1.0},"4":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"35":{"tf":1.0}}},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"29":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"10":{"tf":1.0}}}},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"40":{"tf":1.0},"45":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"y":{"df":2,"docs":{"22":{"tf":2.23606797749979},"36":{"tf":1.0}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}}}}},"v":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":2,"docs":{"10":{"tf":1.0},"11":{"tf":1.0}}}}},"df":0,"docs":{}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.0}}}}},"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"df":1,"docs":{"19":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"10":{"tf":1.7320508075688772},"44":{"tf":1.0}}}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"b":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"40":{"tf":1.0}}}},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"32":{"tf":1.0},"33":{"tf":1.0}}}},"u":{"d":{"df":1,"docs":{"19":{"tf":1.0}}},"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"19":{"tf":1.4142135623730951},"31":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"31":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"19":{"tf":1.0},"31":{"tf":1.7320508075688772}}}}},"df":0,"docs":{}}}},"s":{"=":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"o":{"b":{"df":0,"docs":{},"j":{"df":1,"docs":{"31":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"x":{"df":2,"docs":{"19":{"tf":1.7320508075688772},"31":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"k":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"u":{"df":0,"docs":{},"g":{"df":1,"docs":{"35":{"tf":1.0}}},"i":{"df":0,"docs":{},"l":{"d":{"df":8,"docs":{"11":{"tf":1.7320508075688772},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.0},"27":{"tf":1.4142135623730951},"32":{"tf":1.0},"41":{"tf":1.0},"43":{"tf":1.0}}},"df":0,"docs":{},"t":{"df":7,"docs":{"19":{"tf":1.0},"29":{"tf":2.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0},"34":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"28":{"tf":1.0}}}}}}},"n":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{}}}},"c":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"33":{"tf":1.0}}}},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"13":{"tf":1.0}}}},"df":0,"docs":{}},"p":{".":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"v":{"2":{".":{"c":{"a":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"p":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"o":{"df":1,"docs":{"11":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":2,"docs":{"18":{"tf":1.0},"46":{"tf":1.0}}}},"t":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"32":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"10":{"tf":1.0}}},"df":0,"docs":{}}}},"i":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"l":{"df":1,"docs":{"38":{"tf":1.0}}}},"df":0,"docs":{}}},"l":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":3,"docs":{"31":{"tf":1.4142135623730951},"37":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"i":{"df":6,"docs":{"10":{"tf":2.449489742783178},"11":{"tf":1.0},"4":{"tf":1.0},"43":{"tf":1.0},"6":{"tf":1.0},"8":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"23":{"tf":2.449489742783178},"4":{"tf":1.0},"6":{"tf":1.0}}}}},"p":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":5,"docs":{"18":{"tf":1.0},"19":{"tf":1.7320508075688772},"20":{"tf":1.0},"21":{"tf":1.0},"4":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"o":{"df":0,"docs":{},"u":{"d":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"o":{"d":{"df":0,"docs":{},"e":{"c":{"df":1,"docs":{"43":{"tf":1.7320508075688772}}},"df":6,"docs":{"1":{"tf":1.0},"18":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":1.0},"25":{"tf":1.0},"9":{"tf":1.0}}}},"df":0,"docs":{},"l":{"a":{"b":{"df":3,"docs":{"0":{"tf":1.0},"13":{"tf":1.7320508075688772},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}},"o":{"df":0,"docs":{},"r":{"=":{"\"":{"df":0,"docs":{},"w":{"df":0,"docs":{},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"30":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}},"s":{".":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"m":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"18":{"tf":1.0},"40":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"4":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"44":{"tf":1.0}}}}},"p":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"45":{"tf":1.4142135623730951},"46":{"tf":1.4142135623730951}}},"t":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":2,"docs":{"11":{"tf":1.0},"34":{"tf":1.0}}}},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}}}}}}},"o":{"df":0,"docs":{},"s":{"df":1,"docs":{"34":{"tf":1.0}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"22":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}}},"n":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.7320508075688772}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"33":{"tf":1.0}}}}}}},"n":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.0},"22":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":4,"docs":{"18":{"tf":1.0},"22":{"tf":1.7320508075688772},"23":{"tf":1.0},"33":{"tf":1.0}}}},"df":0,"docs":{}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"43":{"tf":1.0}}}},"n":{"df":1,"docs":{"22":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"23":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"25":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"25":{"tf":1.0},"4":{"tf":1.0}}}},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"14":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"df":7,"docs":{"11":{"tf":1.0},"16":{"tf":1.0},"23":{"tf":1.0},"25":{"tf":1.0},"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}}}}}}}},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"27":{"tf":1.4142135623730951}},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":2,"docs":{"0":{"tf":1.0},"25":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":5,"docs":{"1":{"tf":1.0},"18":{"tf":2.23606797749979},"23":{"tf":1.0},"40":{"tf":1.0},"45":{"tf":1.0}},"e":{"_":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":1,"docs":{"14":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"27":{"tf":1.0},"40":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"21":{"tf":1.0}}}}}},"t":{"df":1,"docs":{"4":{"tf":1.0}}}},"v":{"2":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"40":{"tf":1.0}}}}}}}}}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}}}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":1,"docs":{"40":{"tf":1.0}}}}}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"_":{"c":{"df":0,"docs":{},"v":{"2":{"_":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":1,"docs":{"9":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"36":{"tf":1.0}}}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":2,"docs":{"14":{"tf":1.0},"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"_":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"14":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"15":{"tf":1.0}}}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"c":{"(":{"*":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":0,"docs":{},"v":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"2":{"df":1,"docs":{"36":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":2,"docs":{"13":{"tf":1.0},"15":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":11,"docs":{"1":{"tf":1.0},"12":{"tf":2.449489742783178},"13":{"tf":1.0},"14":{"tf":2.0},"15":{"tf":1.4142135623730951},"2":{"tf":2.0},"35":{"tf":1.4142135623730951},"36":{"tf":1.0},"40":{"tf":1.0},"5":{"tf":1.0},"9":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"44":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"b":{"a":{"df":0,"docs":{},"s":{"df":2,"docs":{"1":{"tf":1.0},"22":{"tf":1.0}},"e":{"/":{"df":0,"docs":{},"v":{"d":{"b":{"df":0,"docs":{},"m":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":11,"docs":{"0":{"tf":1.7320508075688772},"1":{"tf":1.0},"19":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":3.1622776601683795},"23":{"tf":1.4142135623730951},"25":{"tf":1.7320508075688772},"40":{"tf":1.0},"45":{"tf":1.4142135623730951},"46":{"tf":1.0},"9":{"tf":1.0}},"—":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"df":2,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"d":{"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}},"f":{"a":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"32":{"tf":1.0}}}}}},"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"40":{"tf":1.7320508075688772}},"i":{"df":0,"docs":{},"n":{"df":7,"docs":{"18":{"tf":1.0},"21":{"tf":1.4142135623730951},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":2.23606797749979},"41":{"tf":1.0}}}}},"m":{"a":{"df":0,"docs":{},"n":{"d":{"df":4,"docs":{"1":{"tf":1.0},"15":{"tf":1.0},"23":{"tf":1.4142135623730951},"45":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"y":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.0},"45":{"tf":1.0}}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":4,"docs":{"11":{"tf":1.0},"2":{"tf":1.0},"27":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}}},"v":{"df":1,"docs":{"10":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"33":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":3,"docs":{"22":{"tf":1.0},"33":{"tf":1.0},"46":{"tf":1.0}}}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"k":{"df":2,"docs":{"13":{"tf":1.0},"15":{"tf":1.4142135623730951}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"15":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"44":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"o":{"c":{"df":2,"docs":{"35":{"tf":1.0},"4":{"tf":1.0}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"9":{"tf":2.0}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"24":{"tf":1.4142135623730951},"25":{"tf":1.0},"3":{"tf":1.4142135623730951}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}},"g":{"df":1,"docs":{"31":{"tf":1.0}}},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":5,"docs":{"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"i":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{":":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"r":{"a":{"df":0,"docs":{},"w":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}},"df":4,"docs":{"22":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0}},"m":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"38":{"tf":1.0}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"30":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"22":{"tf":1.0},"30":{"tf":1.7320508075688772}}}}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"l":{"df":7,"docs":{"16":{"tf":2.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"5":{"tf":1.0}}}},"u":{"df":0,"docs":{},"e":{"df":1,"docs":{"13":{"tf":1.0}}}}},"df":0,"docs":{},"e":{".":{"df":0,"docs":{},"g":{"df":1,"docs":{"43":{"tf":1.4142135623730951}}}},"a":{"c":{"df":0,"docs":{},"h":{"df":3,"docs":{"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"4":{"tf":1.0}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"40":{"tf":1.0}},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"2":{"tf":1.0}}}}}}}},"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":4,"docs":{"1":{"tf":1.0},"23":{"tf":1.0},"4":{"tf":1.0},"45":{"tf":1.4142135623730951}},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"i":{"df":2,"docs":{"1":{"tf":1.0},"22":{"tf":1.0}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{"df":1,"docs":{"38":{"tf":1.0}},"e":{"2":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}}},"m":{"b":{"df":0,"docs":{},"e":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"n":{"a":{"b":{"df":0,"docs":{},"l":{"df":4,"docs":{"1":{"tf":1.4142135623730951},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"d":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"32":{"tf":1.0},"43":{"tf":1.0}}}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"43":{"tf":1.0}}}}}}}},"x":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"30":{"tf":1.0}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":9,"docs":{"10":{"tf":1.0},"14":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"22":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.0}}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"24":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":2,"docs":{"10":{"tf":1.0},"24":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"45":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"f":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"a":{"c":{"df":0,"docs":{},"e":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{}},"q":{"df":5,"docs":{"42":{"tf":1.7320508075688772},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.0}}},"r":{"df":1,"docs":{"45":{"tf":1.0}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"1":{"tf":1.0},"23":{"tf":1.0}}}}}}},"df":1,"docs":{"40":{"tf":2.0}},"e":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":2,"docs":{"35":{"tf":1.0},"41":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"35":{"tf":1.0}}}},"w":{"df":2,"docs":{"18":{"tf":1.0},"23":{"tf":1.0}}}},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"'":{"df":1,"docs":{"32":{"tf":1.0}}},"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"b":{"a":{"df":0,"docs":{},"v":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":5,"docs":{"11":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.4142135623730951},"43":{"tf":1.0},"45":{"tf":2.0}}}}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":4,"docs":{"26":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.0},"9":{"tf":1.0}},"s":{"df":0,"docs":{},"y":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":1,"docs":{"44":{"tf":1.0}}}}}}}}},"l":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"'":{"df":1,"docs":{"33":{"tf":1.0}}},"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":21,"docs":{"12":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.7320508075688772},"22":{"tf":1.7320508075688772},"26":{"tf":1.0},"28":{"tf":2.449489742783178},"29":{"tf":2.449489742783178},"30":{"tf":1.4142135623730951},"31":{"tf":1.4142135623730951},"32":{"tf":2.0},"33":{"tf":2.6457513110645907},"34":{"tf":1.4142135623730951},"35":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.0},"38":{"tf":1.0},"39":{"tf":1.0},"40":{"tf":3.0},"41":{"tf":1.0},"45":{"tf":1.0}}}}}},"n":{"a":{"df":0,"docs":{},"l":{"_":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}},"df":1,"docs":{"4":{"tf":1.0}}}},"d":{"df":3,"docs":{"2":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"18":{"tf":1.0}}}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"d":{"=":{"'":{"<":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":1,"docs":{"24":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"=":{"'":{"_":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"_":{"_":{"df":1,"docs":{"24":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":1,"docs":{"24":{"tf":1.0}}}},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"25":{"tf":1.0}}}}},"m":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"o":{"c":{"df":0,"docs":{},"u":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"b":{"2":{"4":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}}},"df":7,"docs":{"1":{"tf":1.0},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"32":{"tf":1.7320508075688772},"34":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":1.7320508075688772}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"p":{"df":4,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"(":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"1":{"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"5":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"20":{"tf":1.0}}}},"df":1,"docs":{"18":{"tf":1.7320508075688772}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{".":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"(":{")":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"36":{"tf":1.0}}}}}}}},"df":14,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":3.1622776601683795},"19":{"tf":1.0},"2":{"tf":1.0},"20":{"tf":1.7320508075688772},"22":{"tf":2.8284271247461903},"30":{"tf":1.0},"31":{"tf":1.0},"32":{"tf":2.23606797749979},"33":{"tf":1.0},"34":{"tf":1.7320508075688772},"36":{"tf":1.0},"40":{"tf":2.6457513110645907}},"r":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"35":{"tf":1.0}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"2":{"tf":1.0}}},"df":0,"docs":{}}}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":2,"docs":{"41":{"tf":1.0},"43":{"tf":1.0}}}},"n":{"c":{"df":1,"docs":{"33":{"tf":1.0}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":9,"docs":{"12":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"20":{"tf":1.0},"22":{"tf":2.0},"35":{"tf":1.4142135623730951},"36":{"tf":1.7320508075688772},"37":{"tf":1.0},"38":{"tf":1.4142135623730951},"39":{"tf":1.0}}}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"41":{"tf":1.0}}}}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":20,"docs":{"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":2.23606797749979},"13":{"tf":1.4142135623730951},"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"16":{"tf":2.23606797749979},"17":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"19":{"tf":1.4142135623730951},"2":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951},"24":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":2.23606797749979},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"11":{"tf":1.0}}}},"p":{"df":0,"docs":{},"u":{"df":1,"docs":{"41":{"tf":1.0}}}},"r":{"a":{"df":0,"docs":{},"y":{"8":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"d":{".":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"(":{"df":0,"docs":{},"h":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"*":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"u":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"44":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"d":{"df":4,"docs":{"13":{"tf":1.0},"17":{"tf":1.0},"2":{"tf":1.0},"24":{"tf":1.0}}},"df":0,"docs":{}}}},"h":{".":{"2":{"6":{"4":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"29":{"tf":1.0}},"l":{"df":2,"docs":{"25":{"tf":1.0},"33":{"tf":1.0}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"e":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":1,"docs":{"20":{"tf":1.7320508075688772}},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"=":{"7":{"2":{"0":{"df":4,"docs":{"20":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"/":{"/":{"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":1,"docs":{"20":{"tf":1.0}}}}}}}}},"df":7,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"2":{"tf":1.4142135623730951},"20":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951}}}}}},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":4,"docs":{"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"2":{"tf":1.0}}}},"p":{"df":1,"docs":{"18":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"'":{"df":1,"docs":{"14":{"tf":1.0}}},"df":3,"docs":{"11":{"tf":1.0},"18":{"tf":1.7320508075688772},"4":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.4142135623730951}}}}}}},"l":{"df":1,"docs":{"23":{"tf":1.0}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"34":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.7320508075688772}}}}},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"20":{"tf":1.0},"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":2,"docs":{"20":{"tf":1.4142135623730951},"34":{"tf":2.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":1,"docs":{"44":{"tf":1.0}},"s":{":":{"/":{"/":{"df":0,"docs":{},"f":{".":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{".":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"d":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"2":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":2,"docs":{"14":{"tf":1.0},"18":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"u":{"b":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"/":{"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":0,"docs":{},"l":{"a":{"b":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"/":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"/":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"n":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"/":{"<":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{">":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"u":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}}}},"i":{".":{"df":2,"docs":{"18":{"tf":1.0},"23":{"tf":1.0}}},"/":{"df":0,"docs":{},"o":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}}}}},"m":{"a":{"df":0,"docs":{},"g":{"df":3,"docs":{"22":{"tf":1.0},"40":{"tf":1.4142135623730951},"46":{"tf":1.0}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":8,"docs":{"12":{"tf":1.0},"23":{"tf":1.0},"26":{"tf":1.0},"33":{"tf":1.0},"35":{"tf":1.4142135623730951},"40":{"tf":1.0},"46":{"tf":1.0},"9":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":9,"docs":{"10":{"tf":1.4142135623730951},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"2":{"tf":1.7320508075688772},"32":{"tf":1.0},"40":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"37":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"37":{"tf":1.0}}}}}}},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":3,"docs":{"18":{"tf":1.7320508075688772},"20":{"tf":1.4142135623730951},"22":{"tf":1.0}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}},"r":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":3,"docs":{"0":{"tf":1.0},"23":{"tf":1.0},"33":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"l":{"df":9,"docs":{"10":{"tf":1.4142135623730951},"11":{"tf":1.0},"13":{"tf":1.7320508075688772},"17":{"tf":1.7320508075688772},"5":{"tf":1.0},"6":{"tf":1.7320508075688772},"7":{"tf":1.4142135623730951},"8":{"tf":1.0},"9":{"tf":1.0}}},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"n":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"a":{"d":{"df":2,"docs":{"15":{"tf":1.0},"18":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"t":{"(":{"c":{"a":{"df":0,"docs":{},"p":{".":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"(":{"c":{"df":0,"docs":{},"v":{"2":{".":{"c":{"a":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}}}}},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":4,"docs":{"18":{"tf":1.0},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951},"40":{"tf":1.0}},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"18":{"tf":1.0}},"r":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"f":{"a":{"c":{"df":5,"docs":{"0":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"4":{"tf":1.4142135623730951},"45":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"n":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.4142135623730951}}}}}}},"r":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":1,"docs":{"22":{"tf":1.0}},"t":{"df":5,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"2":{"tf":1.0},"3":{"tf":1.0},"4":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"p":{"c":{"df":1,"docs":{"33":{"tf":2.449489742783178}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"35":{"tf":1.0}}}}},"t":{"'":{"df":3,"docs":{"18":{"tf":1.0},"23":{"tf":1.0},"26":{"tf":1.0}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":2,"docs":{"11":{"tf":1.0},"22":{"tf":1.0}}}}}}}},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"a":{"d":{"(":{"df":0,"docs":{},"r":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":3,"docs":{"19":{"tf":1.0},"23":{"tf":1.0},"31":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"y":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951}}}}}}},"k":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}}}}},"df":0,"docs":{}}},"l":{"a":{"b":{"df":1,"docs":{"0":{"tf":1.0}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"u":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"23":{"tf":2.0},"4":{"tf":1.0}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"22":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"20":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"12":{"tf":1.0},"5":{"tf":1.0}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"22":{"tf":1.0},"34":{"tf":1.0},"4":{"tf":1.0}}}}}},"z":{"df":0,"docs":{},"y":{"/":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"35":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"'":{"df":1,"docs":{"19":{"tf":1.0}}},"df":1,"docs":{"18":{"tf":1.4142135623730951}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"23":{"tf":1.0},"33":{"tf":1.0}}}}}},"i":{"b":{")":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"25":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"a":{"df":0,"docs":{},"v":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{},"f":{"d":{"df":0,"docs":{},"k":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"v":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}}}}},"r":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":9,"docs":{"11":{"tf":1.0},"23":{"tf":2.449489742783178},"25":{"tf":1.7320508075688772},"26":{"tf":1.0},"4":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":1.0},"45":{"tf":1.0},"6":{"tf":1.0}}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":4,"docs":{"23":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":4,"docs":{"0":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"4":{"tf":1.0}}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":3,"docs":{"23":{"tf":1.0},"38":{"tf":1.0},"4":{"tf":1.0}}},"k":{"df":5,"docs":{"11":{"tf":1.0},"15":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"27":{"tf":1.0}}}},"s":{"df":0,"docs":{},"t":{"[":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":2,"docs":{"41":{"tf":1.0},"43":{"tf":1.0}}}}},"o":{"a":{"d":{"df":2,"docs":{"19":{"tf":1.4142135623730951},"22":{"tf":1.0}}},"df":0,"docs":{}},"c":{"a":{"df":0,"docs":{},"l":{"df":3,"docs":{"23":{"tf":1.0},"44":{"tf":1.0},"9":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.0}}}}},"m":{"a":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"45":{"tf":1.0}}}}}},"k":{"df":0,"docs":{},"e":{"df":1,"docs":{"40":{"tf":1.0}}}},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"43":{"tf":1.0}}}},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"18":{"tf":1.0}}}},"t":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":1,"docs":{"36":{"tf":1.0}}}}}}}},"c":{"df":0,"docs":{},"h":{"df":2,"docs":{"18":{"tf":1.0},"32":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"i":{"a":{"df":2,"docs":{"43":{"tf":1.0},"45":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"d":{"=":{"\"":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"k":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"f":{"_":{"df":0,"docs":{},"u":{"d":{"df":0,"docs":{},"f":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}}},"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"d":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"32":{"tf":1.0},"35":{"tf":1.0}}}}},"o":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":2,"docs":{"22":{"tf":2.23606797749979},"4":{"tf":1.0}}}},"u":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}},"df":1,"docs":{"35":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":1,"docs":{"45":{"tf":1.0}}}},"v":{"df":1,"docs":{"43":{"tf":1.0}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"25":{"tf":1.0}}}}}}},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"46":{"tf":1.0}}}}}}}},"p":{"4":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"23":{"tf":1.0},"41":{"tf":1.0}},"m":{"df":0,"docs":{},"e":{"d":{"df":0,"docs":{},"i":{"a":{"df":1,"docs":{"26":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}},"p":{"df":0,"docs":{},"l":{"df":2,"docs":{"18":{"tf":1.0},"34":{"tf":1.0}}}}}}}},"v":{"df":1,"docs":{"10":{"tf":1.0}}},"y":{"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"/":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{":":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"df":0,"docs":{},"m":{"df":0,"docs":{},"y":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}}},"df":0,"docs":{},"v":{"df":0,"docs":{},"f":{".":{"df":0,"docs":{},"u":{"d":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}}},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":4,"docs":{"18":{"tf":1.0},"32":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":2.0}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"df":1,"docs":{"20":{"tf":1.4142135623730951}},"e":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"26":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"d":{"df":4,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0},"35":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":1,"docs":{"13":{"tf":1.0}}}}}}},"w":{"df":1,"docs":{"40":{"tf":1.4142135623730951}},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"40":{"tf":1.0}}}}},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"25":{"tf":1.0}},"e":{"df":2,"docs":{"15":{"tf":1.0},"32":{"tf":1.7320508075688772}}}},"t":{"df":0,"docs":{},"e":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":3,"docs":{"15":{"tf":1.7320508075688772},"18":{"tf":1.0},"21":{"tf":1.0}}}}}},"df":2,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0}}}},"w":{"df":4,"docs":{"18":{"tf":2.0},"19":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.0}}}},"u":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"36":{"tf":1.0}}}}}}},"o":{"b":{"df":0,"docs":{},"j":{"df":1,"docs":{"31":{"tf":1.0}},"e":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":1,"docs":{"14":{"tf":1.0}},"n":{"df":2,"docs":{"32":{"tf":1.0},"34":{"tf":1.0}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"v":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"39":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"g":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"c":{"df":1,"docs":{"38":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}}}}},"/":{"c":{"df":0,"docs":{},"v":{"2":{"df":7,"docs":{"28":{"tf":1.0},"35":{"tf":1.7320508075688772},"36":{"tf":1.0},"37":{"tf":1.0},"38":{"tf":1.0},"39":{"tf":1.0},"46":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":9,"docs":{"11":{"tf":1.0},"12":{"tf":1.0},"2":{"tf":1.0},"26":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.4142135623730951},"4":{"tf":1.0},"46":{"tf":1.0}}}},"d":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}},"df":4,"docs":{"0":{"tf":1.0},"13":{"tf":1.0},"2":{"tf":1.0},"4":{"tf":1.0}}}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":1,"docs":{"22":{"tf":1.0}}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.7320508075688772}}}}}},"r":{"c":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":1,"docs":{"46":{"tf":1.0}}}}}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"18":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"0":{"tf":1.0}}}},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"14":{"tf":1.0}}},"t":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}},"df":5,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"23":{"tf":1.4142135623730951},"41":{"tf":1.0}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"4":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":5,"docs":{"18":{"tf":2.0},"19":{"tf":1.0},"22":{"tf":1.0},"36":{"tf":1.0},"40":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"19":{"tf":1.0},"20":{"tf":1.0},"23":{"tf":1.0},"40":{"tf":1.0}},"l":{"a":{"df":0,"docs":{},"y":{"df":2,"docs":{"19":{"tf":1.0},"21":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"p":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":1,"docs":{"12":{"tf":1.0}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"22":{"tf":1.0}}}}},"r":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"26":{"tf":1.0}}}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"15":{"tf":1.0}}}}},"df":1,"docs":{"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"31":{"tf":1.0}}}}}}},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"7":{"tf":1.0}},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"t":{"df":1,"docs":{"4":{"tf":1.0}}},"x":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"b":{"2":{"4":{"df":2,"docs":{"32":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":3,"docs":{"18":{"tf":1.0},"20":{"tf":1.0},"32":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":3,"docs":{"22":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"40":{"tf":1.0}}}}}},"l":{"a":{"c":{"df":0,"docs":{},"e":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"23":{"tf":1.0}}}},"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}},"y":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":6,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":2.6457513110645907},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"36":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"r":{"df":0,"docs":{},"t":{"=":{"8":{"0":{"0":{"0":{"df":2,"docs":{"18":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"41":{"tf":1.0}}}}}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":2,"docs":{"1":{"tf":1.0},"15":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.7320508075688772}}}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"40":{"tf":1.0}}}}}},"i":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"22":{"tf":1.0}}}}}}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}}}},"df":3,"docs":{"18":{"tf":1.4142135623730951},"40":{"tf":1.0},"9":{"tf":1.0}}}}},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":5,"docs":{"1":{"tf":1.0},"23":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"46":{"tf":1.0}}}}}},"df":1,"docs":{"4":{"tf":1.0}},"g":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"45":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":3,"docs":{"12":{"tf":1.0},"23":{"tf":1.0},"35":{"tf":1.0}}}}}}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":4,"docs":{"0":{"tf":1.0},"23":{"tf":1.4142135623730951},"4":{"tf":1.4142135623730951},"40":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"44":{"tf":1.0}}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"d":{"df":2,"docs":{"0":{"tf":1.0},"23":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":1,"docs":{"24":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"9":{"tf":1.0}}}},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}},"y":{"df":10,"docs":{"16":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":2.23606797749979},"3":{"tf":1.0},"33":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0},"7":{"tf":1.4142135623730951}},"p":{"df":0,"docs":{},"i":{"df":2,"docs":{"0":{"tf":1.0},"24":{"tf":1.4142135623730951}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":6,"docs":{"2":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"6":{"tf":1.0}}}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"1":{"tf":1.0},"4":{"tf":1.0}}}}},"i":{"c":{"df":0,"docs":{},"k":{"df":3,"docs":{"2":{"tf":1.4142135623730951},"24":{"tf":1.0},"25":{"tf":1.0}}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"18":{"tf":1.0}}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"(":{"0":{"df":1,"docs":{"20":{"tf":1.0}}},"2":{"4":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"t":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.0}}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"22":{"tf":1.0}}}}}}},"df":1,"docs":{"19":{"tf":1.0}},"e":{"a":{"d":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"z":{"df":1,"docs":{"23":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"34":{"tf":1.0}}}}}},"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"18":{"tf":1.0}}}}},"t":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":1,"docs":{"38":{"tf":1.0}}}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":3,"docs":{"23":{"tf":1.0},"45":{"tf":1.0},"9":{"tf":1.4142135623730951}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"l":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}}},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.4142135623730951}}}}},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"df":0,"docs":{},"t":{"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"40":{"tf":1.0}}}},"df":5,"docs":{"15":{"tf":1.0},"18":{"tf":2.0},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"l":{"a":{"c":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":1,"docs":{"11":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":3,"docs":{"1":{"tf":1.0},"22":{"tf":2.0},"23":{"tf":1.0}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"33":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"r":{"df":4,"docs":{"11":{"tf":1.0},"27":{"tf":1.0},"34":{"tf":1.0},"6":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"r":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"22":{"tf":1.0},"32":{"tf":1.0}}}}}},"t":{"df":1,"docs":{"23":{"tf":1.0}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":10,"docs":{"1":{"tf":1.4142135623730951},"13":{"tf":1.0},"15":{"tf":1.7320508075688772},"18":{"tf":1.4142135623730951},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951}}}},"t":{"df":1,"docs":{"45":{"tf":1.0}}}}},"t":{"df":3,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"2":{"tf":1.4142135623730951}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"v":{"df":1,"docs":{"1":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":7,"docs":{"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.4142135623730951},"22":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"40":{"tf":2.6457513110645907}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"g":{"b":{"2":{"4":{"df":3,"docs":{"22":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"20":{"tf":1.0},"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":1,"docs":{"33":{"tf":1.0}}}}}},"m":{"df":1,"docs":{"9":{"tf":1.0}}},"o":{"a":{"d":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"p":{"df":1,"docs":{"41":{"tf":1.7320508075688772}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"u":{"df":0,"docs":{},"n":{"df":4,"docs":{"15":{"tf":1.0},"33":{"tf":1.0},"43":{"tf":1.0},"9":{"tf":1.0}}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.0},"26":{"tf":1.0}},"y":{"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"27":{"tf":1.0}}}}}}}}},"df":0,"docs":{}}}}}},"s":{"3":{"df":1,"docs":{"44":{"tf":1.0}}},"a":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":1,"docs":{"26":{"tf":1.0}}}},"m":{"df":0,"docs":{},"e":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"33":{"tf":1.0}}},"p":{"df":0,"docs":{},"l":{"df":4,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"e":{"df":4,"docs":{"13":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"9":{"tf":1.0}}}}},"c":{"a":{"df":0,"docs":{},"l":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"(":{"df":0,"docs":{},"f":{"df":1,"docs":{"40":{"tf":1.0}},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"32":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"[":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}}},"df":4,"docs":{"23":{"tf":1.4142135623730951},"32":{"tf":2.0},"40":{"tf":1.0},"41":{"tf":1.0}}}}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"a":{"df":1,"docs":{"31":{"tf":1.0}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":2,"docs":{"14":{"tf":1.0},"2":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"18":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":4,"docs":{"12":{"tf":1.0},"13":{"tf":1.0},"17":{"tf":1.0},"35":{"tf":1.0}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}}}},"r":{"df":0,"docs":{},"v":{"df":2,"docs":{"23":{"tf":1.0},"45":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":9,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.7320508075688772},"23":{"tf":2.6457513110645907},"33":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":1.7320508075688772}}}},"i":{"c":{"df":3,"docs":{"23":{"tf":1.0},"26":{"tf":1.0},"44":{"tf":1.0}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"32":{"tf":1.0}}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"29":{"tf":1.0}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"43":{"tf":1.0}}}},"w":{"df":1,"docs":{"21":{"tf":1.0}}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.0}}}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":3,"docs":{"22":{"tf":1.0},"23":{"tf":1.0},"40":{"tf":1.0}}}}},"z":{"df":0,"docs":{},"e":{"=":{"4":{"8":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"k":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"15":{"tf":1.0}}}}},"n":{"a":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"r":{"c":{"df":7,"docs":{"11":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"36":{"tf":1.0},"4":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"'":{"df":1,"docs":{"22":{"tf":1.4142135623730951}}},".":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"df":7,"docs":{"18":{"tf":1.7320508075688772},"19":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":2.0},"36":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0}},"i":{"df":0,"docs":{},"f":{"df":3,"docs":{"1":{"tf":1.7320508075688772},"23":{"tf":1.0},"36":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"e":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}}}},"q":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{},"n":{"d":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"t":{"df":22,"docs":{"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":2.23606797749979},"13":{"tf":1.4142135623730951},"14":{"tf":1.4142135623730951},"15":{"tf":1.7320508075688772},"16":{"tf":2.23606797749979},"17":{"tf":1.4142135623730951},"18":{"tf":2.23606797749979},"19":{"tf":1.4142135623730951},"2":{"tf":2.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.4142135623730951},"23":{"tf":1.0},"24":{"tf":1.0},"29":{"tf":1.0},"3":{"tf":1.0},"5":{"tf":2.23606797749979},"6":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0},"9":{"tf":1.0}}}},"t":{"df":0,"docs":{},"u":{"df":3,"docs":{"37":{"tf":1.4142135623730951},"38":{"tf":1.0},"39":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"46":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"g":{"df":2,"docs":{"26":{"tf":1.0},"44":{"tf":1.0}}}},"df":0,"docs":{}}},"r":{"df":3,"docs":{"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}},"e":{"a":{"df":0,"docs":{},"m":{"/":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"13":{"tf":1.0}}}},"df":0,"docs":{}}}},"=":{"0":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"15":{"tf":1.7320508075688772},"18":{"tf":1.0},"23":{"tf":1.0}}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":2,"docs":{"33":{"tf":1.0},"40":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":1,"docs":{"26":{"tf":1.0}}}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":2,"docs":{"23":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}}},"u":{"b":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":0,"docs":{}}}}},"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"22":{"tf":1.7320508075688772}}}},"d":{"df":0,"docs":{},"o":{"df":1,"docs":{"10":{"tf":1.7320508075688772}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.4142135623730951}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":1,"docs":{"41":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":5,"docs":{"33":{"tf":1.0},"35":{"tf":1.4142135623730951},"40":{"tf":1.0},"43":{"tf":2.0},"44":{"tf":1.0}}}}}}}},"y":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":2,"docs":{"22":{"tf":1.0},"23":{"tf":1.0}}}}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":3,"docs":{"22":{"tf":1.0},"23":{"tf":1.0},"46":{"tf":1.0}},"s":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"25":{"tf":1.0}}}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":3,"docs":{"0":{"tf":1.0},"23":{"tf":1.7320508075688772},"33":{"tf":1.0}}}}}}}},"t":{"a":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":3,"docs":{"18":{"tf":1.0},"22":{"tf":1.0},"40":{"tf":1.0}}}},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"27":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"k":{"df":2,"docs":{"22":{"tf":1.0},"46":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"21":{"tf":1.4142135623730951}}}}}}}}},"n":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"41":{"tf":1.0}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.0}}}},"x":{"df":0,"docs":{},"t":{"=":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"30":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":3,"docs":{"22":{"tf":1.0},"30":{"tf":1.0},"40":{"tf":1.4142135623730951}}}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"18":{"tf":1.4142135623730951}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"20":{"tf":1.0}}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":1,"docs":{"6":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"18":{"tf":1.4142135623730951}},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":3,"docs":{"18":{"tf":1.7320508075688772},"19":{"tf":1.0},"22":{"tf":1.7320508075688772}}}}},"df":0,"docs":{}}}}}},"o":{"df":1,"docs":{"18":{"tf":1.0}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":3,"docs":{"23":{"tf":1.0},"34":{"tf":1.0},"4":{"tf":1.0}}}}}},"o":{"df":0,"docs":{},"l":{"df":6,"docs":{"23":{"tf":2.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"27":{"tf":1.0},"4":{"tf":1.0}}}},"s":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.4142135623730951},"19":{"tf":1.0}}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"[":{"df":0,"docs":{},"i":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"19":{"tf":1.0}}}},"[":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.0},"19":{"tf":1.0}}}},"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":6,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.4142135623730951},"23":{"tf":1.0},"25":{"tf":1.4142135623730951},"32":{"tf":1.0},"4":{"tf":1.0}}}}}},"p":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"1":{"tf":1.0},"23":{"tf":1.0}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":1,"docs":{"1":{"tf":1.0}}}}}}}},"df":0,"docs":{},"i":{"df":2,"docs":{"18":{"tf":1.0},"34":{"tf":1.0}}},"u":{"df":0,"docs":{},"e":{"df":3,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0}}}}},"y":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":3,"docs":{"22":{"tf":1.0},"32":{"tf":1.0},"40":{"tf":1.0}}}}}},"u":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"2":{"2":{".":{"0":{"4":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"d":{"df":0,"docs":{},"f":{"df":3,"docs":{"28":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.7320508075688772}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"x":{"df":1,"docs":{"40":{"tf":1.0}}}},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":1,"docs":{"23":{"tf":1.0}},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"33":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"l":{"df":1,"docs":{"9":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"b":{".":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"(":{"\"":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{":":{"/":{"/":{"df":0,"docs":{},"f":{".":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"k":{".":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"d":{"a":{"df":0,"docs":{},"t":{"a":{"/":{"d":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"2":{"/":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"_":{"7":{"2":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}},"df":1,"docs":{"19":{"tf":1.0}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"s":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":20,"docs":{"1":{"tf":1.0},"10":{"tf":1.0},"14":{"tf":1.0},"15":{"tf":1.0},"18":{"tf":2.23606797749979},"2":{"tf":1.0},"22":{"tf":1.4142135623730951},"23":{"tf":2.8284271247461903},"24":{"tf":1.0},"26":{"tf":1.7320508075688772},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":1.7320508075688772},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.4142135623730951},"6":{"tf":1.0},"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":6,"docs":{"21":{"tf":1.4142135623730951},"28":{"tf":1.0},"29":{"tf":1.0},"33":{"tf":1.0},"40":{"tf":2.0},"41":{"tf":1.0}}}},"r":{"/":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"/":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"v":{"2":{"df":0,"docs":{},"v":{"df":1,"docs":{"22":{"tf":1.0}}}},"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":1,"docs":{"32":{"tf":1.0}}}},"r":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"b":{"df":0,"docs":{},"m":{"df":1,"docs":{"23":{"tf":1.0}}}},"df":0,"docs":{}},"df":1,"docs":{"9":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":3,"docs":{"0":{"tf":1.4142135623730951},"24":{"tf":1.0},"25":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}}}}},"f":{".":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"(":{"\"":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"df":1,"docs":{"19":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"h":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"'":{"df":0,"docs":{},"s":{"c":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"(":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":3,"docs":{"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"u":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"40":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"y":{"df":0,"docs":{},"p":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"y":{"df":0,"docs":{},"r":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":1,"docs":{"10":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"(":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"\"":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"\"":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"'":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}}}},"df":4,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.0},"40":{"tf":1.0},"9":{"tf":1.0}},"r":{"df":1,"docs":{"18":{"tf":1.0}}}},"i":{"a":{"df":2,"docs":{"23":{"tf":1.0},"35":{"tf":1.0}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"'":{"df":1,"docs":{"18":{"tf":1.0}}},"c":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"37":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":19,"docs":{"0":{"tf":1.7320508075688772},"1":{"tf":2.0},"14":{"tf":1.0},"15":{"tf":2.0},"18":{"tf":3.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":1.7320508075688772},"23":{"tf":2.8284271247461903},"25":{"tf":2.23606797749979},"26":{"tf":1.4142135623730951},"36":{"tf":1.0},"4":{"tf":2.0},"43":{"tf":1.4142135623730951},"44":{"tf":1.4142135623730951},"45":{"tf":1.0},"46":{"tf":1.0},"9":{"tf":1.0}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"36":{"tf":1.0},"37":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{".":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"c":{"df":1,"docs":{"36":{"tf":1.0}}},"df":0,"docs":{}}}}},"_":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"c":{"df":1,"docs":{"37":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"df":0,"docs":{}}}}}}}}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":30,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":2.23606797749979},"10":{"tf":2.0},"11":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":1.0},"16":{"tf":1.0},"18":{"tf":1.0},"22":{"tf":1.0},"23":{"tf":3.0},"24":{"tf":2.449489742783178},"25":{"tf":1.4142135623730951},"28":{"tf":1.0},"29":{"tf":1.0},"3":{"tf":1.4142135623730951},"32":{"tf":1.0},"33":{"tf":1.0},"36":{"tf":1.4142135623730951},"4":{"tf":3.3166247903554},"40":{"tf":2.0},"41":{"tf":1.0},"43":{"tf":2.449489742783178},"44":{"tf":1.0},"45":{"tf":2.6457513110645907},"46":{"tf":1.7320508075688772},"5":{"tf":1.0},"6":{"tf":1.7320508075688772},"7":{"tf":1.7320508075688772},"8":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"r":{"'":{"df":1,"docs":{"2":{"tf":1.0}}},".":{"c":{"df":0,"docs":{},"v":{"2":{"df":6,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.0},"2":{"tf":1.4142135623730951},"24":{"tf":1.0},"35":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"_":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"=":{"'":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":1,"docs":{"10":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":2,"docs":{"20":{"tf":1.0},"21":{"tf":1.4142135623730951}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"o":{"d":{"df":1,"docs":{"23":{"tf":2.23606797749979}}},"df":0,"docs":{}},"p":{"8":{"df":1,"docs":{"43":{"tf":1.0}}},"df":0,"docs":{}},"s":{"df":1,"docs":{"18":{"tf":1.0}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"(":{"*":{"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"20":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":2,"docs":{"20":{"tf":1.4142135623730951},"34":{"tf":1.7320508075688772}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"w":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"k":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":2,"docs":{"12":{"tf":1.0},"16":{"tf":1.0}}}}}}}}}}},"n":{"df":0,"docs":{},"t":{"df":3,"docs":{"18":{"tf":1.0},"23":{"tf":1.7320508075688772},"9":{"tf":1.0}}}},"y":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":1,"docs":{"20":{"tf":1.7320508075688772}},"e":{"b":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"41":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"3":{"tf":1.0},"4":{"tf":1.0}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":2,"docs":{"23":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{},"l":{"df":2,"docs":{"18":{"tf":1.0},"43":{"tf":1.0}}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"10":{"tf":1.0}}}}},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"=":{"1":{"2":{"8":{"0":{"df":4,"docs":{"20":{"tf":1.0},"32":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"20":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}}}},"df":7,"docs":{"14":{"tf":1.4142135623730951},"15":{"tf":1.4142135623730951},"18":{"tf":1.0},"2":{"tf":1.4142135623730951},"20":{"tf":1.4142135623730951},"32":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"20":{"tf":1.0}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"n":{"'":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"k":{"df":11,"docs":{"12":{"tf":1.0},"13":{"tf":1.4142135623730951},"15":{"tf":1.0},"18":{"tf":1.7320508075688772},"23":{"tf":1.4142135623730951},"26":{"tf":1.0},"35":{"tf":1.0},"4":{"tf":1.4142135623730951},"43":{"tf":1.4142135623730951},"44":{"tf":1.0},"45":{"tf":1.7320508075688772}},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.4142135623730951}}}}}}},"l":{"d":{"df":6,"docs":{"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"18":{"tf":1.4142135623730951},"2":{"tf":1.0},"30":{"tf":1.0},"40":{"tf":1.0}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"18":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"15":{"tf":1.0},"23":{"tf":1.4142135623730951}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"26":{"tf":1.0}}}}}}}}},"x":{"1":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"2":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"=":{"1":{"0":{"0":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"10":{"tf":1.0}}},"y":{"1":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"2":{"df":1,"docs":{"31":{"tf":1.4142135623730951}}},"=":{"1":{"0":{"0":{"df":1,"docs":{"30":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"10":{"tf":1.0}},"e":{"df":1,"docs":{"44":{"tf":1.0}}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":1,"docs":{"4":{"tf":1.0}}}},"u":{"'":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"35":{"tf":1.0}}}}}}}}},"r":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":3,"docs":{"23":{"tf":2.23606797749979},"6":{"tf":1.0},"9":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"v":{"4":{"2":{"0":{"df":0,"docs":{},"p":{"df":3,"docs":{"18":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"title":{"root":{"a":{"c":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"44":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":1.0}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"19":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"x":{"df":1,"docs":{"31":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}},"x":{"df":1,"docs":{"19":{"tf":1.0}}}},"u":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"d":{"df":2,"docs":{"11":{"tf":1.0},"27":{"tf":1.0}}},"df":0,"docs":{},"t":{"df":1,"docs":{"29":{"tf":1.0}}}}}}},"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"8":{"tf":1.0}}}},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"r":{"df":2,"docs":{"45":{"tf":1.0},"46":{"tf":1.0}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"20":{"tf":1.0}}}}}}}},"n":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}}},"df":0,"docs":{}}},"v":{"2":{"df":1,"docs":{"12":{"tf":1.0}}},"df":0,"docs":{}}},"d":{"a":{"df":0,"docs":{},"t":{"a":{"df":3,"docs":{"0":{"tf":1.0},"22":{"tf":1.0},"25":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"21":{"tf":1.0},"40":{"tf":1.0}}}}}},"o":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"9":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"3":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"r":{"a":{"df":0,"docs":{},"w":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"df":1,"docs":{"30":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"l":{"df":1,"docs":{"16":{"tf":1.0}}}}},"df":0,"docs":{},"f":{"a":{"df":0,"docs":{},"q":{"df":1,"docs":{"42":{"tf":1.0}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"g":{"df":1,"docs":{"45":{"tf":1.0}}}}}}},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":4,"docs":{"21":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"40":{"tf":1.0}}}}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"43":{"tf":1.0}}}},"df":0,"docs":{}}}},"u":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"35":{"tf":1.0},"36":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":3,"docs":{"12":{"tf":1.0},"16":{"tf":1.0},"5":{"tf":1.0}}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":2,"docs":{"14":{"tf":1.0},"18":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"l":{"df":3,"docs":{"13":{"tf":1.0},"17":{"tf":1.0},"6":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.0}}}}}}}}},"p":{"c":{"df":1,"docs":{"33":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"25":{"tf":1.0}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"m":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"v":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"39":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"g":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"c":{"df":1,"docs":{"38":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"/":{"c":{"df":0,"docs":{},"v":{"2":{"df":2,"docs":{"35":{"tf":1.0},"46":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":1,"docs":{"37":{"tf":1.0}}}},"df":0,"docs":{}}}}},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"4":{"tf":1.0}}}},"df":0,"docs":{}}}}},"y":{"df":2,"docs":{"24":{"tf":1.0},"7":{"tf":1.0}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"2":{"tf":1.0}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"44":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"15":{"tf":1.0}}}}}}},"o":{"a":{"d":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"p":{"df":1,"docs":{"41":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"s":{"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":1,"docs":{"32":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"c":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":1,"docs":{"36":{"tf":1.0}}}}},"df":0,"docs":{}}},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":4,"docs":{"12":{"tf":1.0},"16":{"tf":1.0},"2":{"tf":1.0},"5":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"15":{"tf":1.0}}}},"df":0,"docs":{}}}},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"43":{"tf":1.0}}}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"21":{"tf":1.0}}}}}}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"23":{"tf":1.0}}}}},"r":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":2,"docs":{"0":{"tf":1.0},"25":{"tf":1.0}}}}}}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"21":{"tf":1.0},"40":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"df":4,"docs":{"0":{"tf":1.0},"25":{"tf":1.0},"43":{"tf":1.0},"44":{"tf":1.0}}}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":11,"docs":{"0":{"tf":1.0},"1":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"36":{"tf":1.0},"43":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.0},"7":{"tf":1.0},"8":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":1,"docs":{"21":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"d":{"df":2,"docs":{"14":{"tf":1.0},"18":{"tf":1.0}}},"df":0,"docs":{}}}}}}}},"lang":"English","pipeline":["trimmer","stopWordFilter","stemmer"],"ref":"id","version":"0.9.5"},"results_options":{"limit_results":30,"teaser_word_count":30},"search_options":{"bool":"OR","expand":true,"fields":{"body":{"boost":1},"breadcrumbs":{"boost":1},"title":{"boost":2}}}} \ No newline at end of file diff --git a/settings.html b/settings.html new file mode 100644 index 0000000..896b9ca --- /dev/null +++ b/settings.html @@ -0,0 +1 @@ +Settings

Rustdoc settings

Back
\ No newline at end of file diff --git a/src-files.js b/src-files.js new file mode 100644 index 0000000..f5e663a --- /dev/null +++ b/src-files.js @@ -0,0 +1,3 @@ +var srcIndex = new Map(JSON.parse('[["vidformer",["",[["av",[],["decoder.rs","demuxer.rs","encoder.rs","framesource.rs","mod.rs","muxer.rs"]],["filter",[["builtin",[],["drawutils.rs","ipc.rs"]]],["builtin.rs","cv2.rs","filter_utils.rs"]]],["array.rs","dve.rs","filter.rs","lib.rs","pool.rs","service.rs","sir.rs","source.rs","spec.rs","util.rs"]]]]')); +createSrcSidebar(); +//{"start":36,"fragment_lengths":[311]} \ No newline at end of file diff --git a/src/vidformer/array.rs.html b/src/vidformer/array.rs.html new file mode 100644 index 0000000..715c218 --- /dev/null +++ b/src/vidformer/array.rs.html @@ -0,0 +1,103 @@ +array.rs - source

vidformer/
array.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
//! Arrays provide access to data.
+//!
+//! Arrays store conventional data (e.g. numbers, strings) and can be referenced by specs.
+//! As with the rest of the vidformer data model, arrays are duel-indexed by a timestamp or a position.
+//! Arrays can be backed by a variety of sources, such as a JSON file or a database.
+
+use num::Rational64;
+
+/// A trait for an array
+pub trait Array: Sync + Send {
+    /// Returns the domain of the array.
+    ///
+    /// The domain is the set of times at which the array is defined.
+    /// Each time corresponds to a single output value at that timestamp.
+    ///
+    /// The output must:
+    /// - Be sorted in ascending order
+    /// - Contain no duplicate values
+    /// - Begin with 0
+    fn domain(&self) -> Vec<Rational64>;
+
+    /// Returns the value at a given positional index.
+    fn index(&self, idx: usize) -> crate::sir::DataExpr;
+
+    /// Returns the value at a given time index.
+    fn index_t(&self, idx: Rational64) -> crate::sir::DataExpr;
+}
+
+/// An array backed by a JSON file
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct JsonArary {
+    array: Vec<(Rational64, crate::sir::DataExpr)>,
+}
+
+impl Array for JsonArary {
+    fn domain(&self) -> Vec<Rational64> {
+        self.array.iter().map(|(t, _)| *t).collect()
+    }
+
+    fn index(&self, idx: usize) -> crate::sir::DataExpr {
+        self.array[idx].1.clone()
+    }
+
+    fn index_t(&self, idx: Rational64) -> crate::sir::DataExpr {
+        let idx = self
+            .array
+            .binary_search_by(|(t, _)| t.partial_cmp(&idx).unwrap())
+            .unwrap();
+        self.index(idx)
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/av/decoder.rs.html b/src/vidformer/av/decoder.rs.html new file mode 100644 index 0000000..32193bc --- /dev/null +++ b/src/vidformer/av/decoder.rs.html @@ -0,0 +1,167 @@ +decoder.rs - source

vidformer/av/
decoder.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
use log::*;
+use rusty_ffmpeg::ffi;
+use std::ptr;
+
+pub struct Decoder {
+    pub codec_context: *mut ffi::AVCodecContext,
+}
+
+pub enum DecoderResult {
+    Frame,
+    Again,
+    Eof,
+}
+
+impl Decoder {
+    pub fn new(
+        codec: *const ffi::AVCodec,
+        codec_parameters: *const ffi::AVCodecParameters,
+    ) -> Result<Self, crate::Error> {
+        let codec_context = unsafe { ffi::avcodec_alloc_context3(codec) };
+
+        if codec_context.is_null() {
+            return Err(crate::Error::AVError(
+                "Failed to allocate memory for codec context".to_string(),
+            ));
+        }
+
+        let response =
+            unsafe { ffi::avcodec_parameters_to_context(codec_context, codec_parameters) };
+
+        if response < 0 {
+            return Err(crate::Error::AVError(
+                "Failed to copy codec parameters to codec context".to_string(),
+            ));
+        }
+
+        let response = unsafe { ffi::avcodec_open2(codec_context, codec, ptr::null_mut()) };
+        if response < 0 {
+            return Err(crate::Error::AVError(
+                "Decoder failed to open codec".to_string(),
+            ));
+        }
+
+        Ok(Decoder { codec_context })
+    }
+
+    pub fn send_packet(&mut self, packet: *mut ffi::AVPacket) {
+        let response = unsafe { ffi::avcodec_send_packet(self.codec_context, packet) };
+
+        if response < 0 {
+            error!("Error sending packet to decoder");
+        }
+    }
+
+    pub fn flush(&mut self) {
+        let response = unsafe { ffi::avcodec_send_packet(self.codec_context, ptr::null_mut()) };
+        if response < 0 {
+            error!("Error flushing decoder");
+        }
+    }
+
+    pub fn read_frame(&mut self, frame: *mut ffi::AVFrame) -> Result<DecoderResult, crate::Error> {
+        let response = unsafe { ffi::avcodec_receive_frame(self.codec_context, frame) };
+
+        if response == ffi::AVERROR(ffi::EAGAIN) {
+            Ok(DecoderResult::Again)
+        } else if response == ffi::AVERROR_EOF {
+            Ok(DecoderResult::Eof)
+        } else if response < 0 {
+            Err(crate::Error::AVError(
+                "Error while receiving a frame from the decoder.".to_string(),
+            ))
+        } else {
+            Ok(DecoderResult::Frame)
+        }
+    }
+
+    pub fn close(&self) {
+        unsafe {
+            ffi::avcodec_free_context(&mut (self.codec_context as *mut _));
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/av/demuxer.rs.html b/src/vidformer/av/demuxer.rs.html new file mode 100644 index 0000000..c884bf5 --- /dev/null +++ b/src/vidformer/av/demuxer.rs.html @@ -0,0 +1,719 @@ +demuxer.rs - source

vidformer/av/
demuxer.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
use log::*;
+use num::Zero;
+use num_rational::Rational64;
+use rusty_ffmpeg::ffi;
+use std::io::Read;
+use std::io::Seek;
+use std::{ptr, slice};
+
+struct IoCtx {
+    canary: u64, // We're doing some unsafe opaque pointer passing, so let's add a canary to make sure we didn't mess up. Valid value is 0xdeadbeef
+    size: u64,
+    buf_reader: std::io::BufReader<opendal::StdReader>,
+    err: Option<std::io::Error>,
+}
+
+unsafe extern "C" fn vidformer_avio_read_packet(
+    opaque: *mut ::std::os::raw::c_void,
+    buf: *mut u8,
+    buf_size: ::std::os::raw::c_int,
+) -> ::std::os::raw::c_int {
+    let io_ctx = &mut *(opaque as *mut IoCtx);
+    debug_assert_eq!(io_ctx.canary, 0xdeadbeef);
+
+    let buf: &mut [u8] = unsafe { slice::from_raw_parts_mut(buf, buf_size as usize) };
+    let read = io_ctx.buf_reader.read(buf);
+    match read {
+        Ok(read) => {
+            if read == 0 {
+                debug_assert!(io_ctx.buf_reader.stream_position().unwrap() == io_ctx.size);
+                ffi::AVERROR_EOF
+            } else {
+                read as i32
+            }
+        }
+        Err(e) => {
+            error!("Error reading packet: {}", e);
+            if io_ctx.err.is_none() {
+                io_ctx.err = Some(e);
+            }
+            ffi::AVERROR_EXTERNAL
+        }
+    }
+}
+
+unsafe extern "C" fn vidformer_avio_seek(
+    opaque: *mut ::std::os::raw::c_void,
+    offset: i64,
+    whence: ::std::os::raw::c_int,
+) -> i64 {
+    let io_ctx = &mut *(opaque as *mut IoCtx);
+    debug_assert_eq!(io_ctx.canary, 0xdeadbeef);
+
+    let whence = match whence as u32 {
+        ffi::SEEK_CUR => std::io::SeekFrom::Current(offset),
+        ffi::SEEK_END => std::io::SeekFrom::End(offset),
+        ffi::SEEK_SET => std::io::SeekFrom::Start(offset as u64),
+        ffi::AVSEEK_SIZE => {
+            // whence == AVSEEK_SIZE is the libav way of asking for the size of the file
+            return io_ctx.size as i64;
+        }
+        ffi::AVSEEK_FORCE => panic!("AVSEEK_FORCE is not supported"), // libav way of saying "seek even if you have to reopen the file"
+        _ => panic!("invalid seek whence ({})", whence,),
+    };
+
+    let seeked = io_ctx.buf_reader.seek(whence);
+    match seeked {
+        Ok(seeked) => seeked as i64,
+        Err(e) => {
+            error!("Error seeking: {}", e);
+            if io_ctx.err.is_none() {
+                io_ctx.err = Some(e);
+            }
+            ffi::AVERROR_EXTERNAL as i64
+        }
+    }
+}
+
+pub struct Demuxer {
+    pub format_context: *mut ffi::AVFormatContext,
+    avio_context: *mut ffi::AVIOContext,
+    #[allow(unused)] // We need to keep this alive since libav keeps it as an opaque pointer
+    io_ctx: std::pin::Pin<std::boxed::Box<IoCtx>>,
+    pub time_base: Rational64,
+    pub codec: *const ffi::AVCodec,
+    pub codec_parameters: *const ffi::AVCodecParameters,
+    pub video_stream_index: Option<usize>,
+    pub stream: *mut ffi::AVStream,
+}
+
+impl Demuxer {
+    pub fn new(
+        file_path: &str,
+        stream_idx: usize,
+        service: &crate::service::Service,
+        file_size: u64,
+        io_runtime_handle: &tokio::runtime::Handle,
+    ) -> Result<Self, crate::Error> {
+        let mut format_context = unsafe { ffi::avformat_alloc_context() };
+        if format_context.is_null() {
+            return Err(crate::Error::AVError(
+                "could not allocate memory for Format Context".to_string(),
+            ));
+        }
+
+        debug!("Opening {} for read", file_path);
+
+        let op = service.blocking_operator(io_runtime_handle)?;
+
+        let reader: opendal::BlockingReader = op.reader(file_path).map_err(|e| {
+            if e.kind() == opendal::ErrorKind::NotFound {
+                crate::Error::IOError(format!("File `{}` not found", file_path))
+            } else {
+                crate::Error::IOError(format!("OpenDAL error: {}", e))
+            }
+        })?;
+
+        let reader: opendal::StdReader = match reader.into_std_read(0..file_size) {
+            Ok(reader) => reader,
+            Err(err) => {
+                return Err(crate::Error::IOError(format!(
+                    "OpenDAL failed to convert BlockingReader to StdReader: {}",
+                    err
+                )));
+            }
+        };
+        let buffered_reader = std::io::BufReader::new(reader);
+
+        let io_ctx = IoCtx {
+            canary: 0xdeadbeef,
+            size: file_size,
+            buf_reader: buffered_reader,
+            err: None,
+        };
+        let io_ctx = Box::pin(io_ctx);
+        let io_ctx_ptr =
+            io_ctx.as_ref().get_ref() as *const IoCtx as *mut IoCtx as *mut ::std::os::raw::c_void;
+
+        let avio_buffer_size = 128 * 1024; // 128KiB buffer, probably good enough for now
+        let avio_buffer: *mut std::ffi::c_void =
+            unsafe { ffi::av_malloc(avio_buffer_size as usize) };
+
+        let avio_context = unsafe {
+            ffi::avio_alloc_context(
+                avio_buffer as *mut u8,
+                avio_buffer_size,
+                0,
+                io_ctx_ptr,
+                Some(vidformer_avio_read_packet),
+                None,
+                Some(vidformer_avio_seek),
+            )
+        };
+
+        if avio_context.is_null() {
+            return Err(crate::Error::AVError(
+                "could not allocate memory for AVIO Context".to_string(),
+            ));
+        }
+
+        unsafe {
+            (*format_context).pb = avio_context;
+        }
+
+        let ret = unsafe {
+            ffi::avformat_open_input(
+                &mut format_context,
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+            )
+        };
+        if ret != 0 {
+            if ret == ffi::AVERROR_EXTERNAL {
+                let err = io_ctx.err.as_ref().unwrap();
+                if err.kind() == std::io::ErrorKind::NotFound {
+                    return Err(crate::Error::IOError(format!(
+                        "File `{}` not found",
+                        file_path
+                    )));
+                } else {
+                    return Err(crate::Error::IOError(format!("OpenDAL error: {}", err)));
+                }
+            }
+
+            let err_str = crate::util::av_strerror(ret);
+            return Err(crate::Error::AVError(format!(
+                "failed to open media format: {}",
+                err_str
+            )));
+        }
+
+        // TODO: This may decode a few frames, which could be slow. Maybe don't do that when actually running a spec?
+        if unsafe { ffi::avformat_find_stream_info(format_context, ptr::null_mut()) } < 0 {
+            return Err(crate::Error::AVError(
+                "could not get the stream info".to_string(),
+            ));
+        }
+
+        let mut codec_ptr: *const ffi::AVCodec = ptr::null_mut();
+        let mut codec_parameters_ptr: *const ffi::AVCodecParameters = ptr::null_mut();
+        let mut video_stream_index = None;
+
+        let streams = unsafe {
+            slice::from_raw_parts_mut(
+                (*format_context).streams,
+                (*format_context).nb_streams as usize,
+            )
+        };
+
+        for (i, stream) in streams
+            .iter_mut()
+            .map(|stream| unsafe { stream.as_mut() }.expect("null stream pointer"))
+            .enumerate()
+        {
+            if i != stream_idx {
+                stream.discard = ffi::AVDiscard_AVDISCARD_ALL;
+                continue;
+            }
+
+            let local_codec_params = unsafe { stream.codecpar.as_ref() }.expect("codecpar is null");
+            let local_codec =
+                unsafe { ffi::avcodec_find_decoder(local_codec_params.codec_id).as_ref() }
+                    .expect("ERROR unsupported codec!");
+
+            if local_codec_params.codec_type == ffi::AVMediaType_AVMEDIA_TYPE_VIDEO {
+                if video_stream_index.is_none() {
+                    video_stream_index = Some(i);
+                    codec_ptr = local_codec;
+                    codec_parameters_ptr = local_codec_params;
+                }
+            } else {
+                println!("Stream {i} is not a video");
+                continue;
+            }
+        }
+
+        let time_base = crate::util::avrat_to_rat(&unsafe { (*streams[stream_idx]).time_base });
+        debug_assert!(!time_base.is_zero());
+
+        Ok(Demuxer {
+            format_context,
+            avio_context,
+            io_ctx,
+            time_base,
+            codec: codec_ptr,
+            codec_parameters: codec_parameters_ptr,
+            video_stream_index,
+            stream: unsafe { streams[stream_idx].as_mut() }.unwrap(),
+        })
+    }
+
+    pub fn seek(&mut self, ts: &Rational64) -> Result<(), crate::Error> {
+        let seek_ts = ts / self.time_base;
+        assert_eq!(*seek_ts.denom(), 1);
+        let seek_ts = *seek_ts.numer();
+
+        debug!("Seeking to {}", ts);
+
+        if unsafe { ffi::avformat_seek_file(self.format_context, 0, seek_ts, seek_ts, seek_ts, 0) }
+            < 0
+        {
+            return Err(crate::Error::AVError("failed to seek file".to_string()));
+        }
+
+        Ok(())
+    }
+
+    pub fn read_packet(&mut self, packet: *mut ffi::AVPacket) -> Option<()> {
+        loop {
+            if unsafe { ffi::av_read_frame(self.format_context, packet) } >= 0 {
+                // debug!(
+                //     "DEMUX - Packet stream index {} pts = {} dts = {} key_frame = {} size = {}",
+                //     unsafe { (*packet).stream_index },
+                //     unsafe { (*packet).pts },
+                //     unsafe { (*packet).dts },
+                //     unsafe { (*packet).flags } as u32 & ffi::AV_PKT_FLAG_KEY != 0,
+                //     unsafe { (*packet).size }
+                // );
+
+                // Is this packet from the correct stream?
+                if unsafe { (*packet).stream_index } as usize == self.video_stream_index.unwrap() {
+                    // If so, we have updated the pointer, so return
+                    return Some(());
+                } else {
+                    // If not, unref the packet and keep trying
+                    unsafe {
+                        ffi::av_packet_unref(packet);
+                    }
+                    continue;
+                }
+            } else {
+                return None;
+            }
+        }
+    }
+
+    pub fn close(&self) {
+        unsafe {
+            ffi::avformat_close_input(&mut (self.format_context as *mut _));
+
+            // Free the avio buffer. libav and us share memory control over it, so its probably not even the one we allocated.
+            // Sorry that pointer casting is so ugly, it makes sure to pass the pointer to the buffer pointer, not the buffer pointer itself.
+            // Probably a better way to do this which doesn't involve using the mut keyword six times in one expression. ¯\_(ツ)_/¯
+            ffi::av_freep(
+                &mut (*self.avio_context).buffer as *mut *mut u8 as *mut *mut std::os::raw::c_void
+                    as *mut std::os::raw::c_void,
+            );
+
+            ffi::av_free(self.avio_context as *mut std::os::raw::c_void);
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use rusty_ffmpeg::ffi;
+
+    const TEST_VID: &str = "../tos_720p.mp4";
+    const TEST_STREAM: usize = 0;
+
+    #[test]
+    fn tos_test() {
+        let service = crate::service::Service::default();
+        let profile = crate::source::SourceVideoStreamMeta::profile(
+            "tos_720p",
+            "../tos_720p.mp4",
+            0,
+            &service,
+        )
+        .unwrap();
+
+        let io_runtime = tokio::runtime::Builder::new_multi_thread()
+            .worker_threads(1)
+            .enable_all()
+            .build()
+            .unwrap();
+
+        let mut demuxer = Demuxer::new(
+            TEST_VID,
+            TEST_STREAM,
+            &service,
+            profile.file_size,
+            io_runtime.handle(),
+        )
+        .unwrap();
+
+        let packet = unsafe { ffi::av_packet_alloc().as_mut() }
+            .expect("failed to allocated memory for AVPacket");
+
+        let mut demuxed_packets = 0;
+        while demuxer.read_packet(packet).is_some() {
+            demuxed_packets += 1;
+        }
+        demuxer.close();
+
+        assert_eq!(demuxed_packets, 17616);
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/av/encoder.rs.html b/src/vidformer/av/encoder.rs.html new file mode 100644 index 0000000..24bf366 --- /dev/null +++ b/src/vidformer/av/encoder.rs.html @@ -0,0 +1,375 @@ +encoder.rs - source

vidformer/av/
encoder.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
use crate::dve::AVFrame;
+use crate::util;
+use log::*;
+use num_rational::Rational64;
+use rusty_ffmpeg::ffi;
+use std::ffi::CString;
+use std::ptr;
+
+use crate::dve::Config;
+
+pub struct Encoder {
+    pub(crate) codec_ctx: *mut ffi::AVCodecContext,
+    pub(crate) packet: *mut ffi::AVPacket,
+    pub(crate) time_base: Rational64,
+    pub(crate) flushed: bool,
+}
+
+impl Encoder {
+    pub(crate) fn new(config: &Config, time_base: &Rational64) -> Result<Self, crate::Error> {
+        let codec = match &config.encoder {
+            Some(enc_cfg) => enc_cfg.avcodec()?,
+            None => {
+                let codec = unsafe { ffi::avcodec_find_encoder(ffi::AVCodecID_AV_CODEC_ID_H264) };
+                match unsafe { codec.as_ref() } {
+                    Some(codec) => codec,
+                    None => panic!("Failed to find default h264 encoder"),
+                }
+            }
+        };
+
+        debug!("Encoder has codec {}", util::fmt_av_codec(codec));
+
+        let codec_ctx: *mut ffi::AVCodecContext = unsafe { ffi::avcodec_alloc_context3(codec) };
+        if codec_ctx.is_null() {
+            return Err(crate::Error::AVError(
+                "Failed to allocate codec context".to_string(),
+            ));
+        }
+
+        let default_opts = &[("preset".to_string(), "ultrafast".to_string())];
+
+        let opts: &[(String, String)] = match &config.encoder {
+            Some(enc_cfg) => &enc_cfg.opts,
+            None => default_opts,
+        };
+
+        for (opt_k, opt_v) in opts {
+            let opt_k_cstr = CString::new(opt_k.clone()).unwrap();
+            let opt_v_cstr = CString::new(opt_v.clone()).unwrap();
+
+            let ret = unsafe {
+                ffi::av_opt_set(
+                    (*codec_ctx).priv_data,
+                    opt_k_cstr.as_ptr(),
+                    opt_v_cstr.as_ptr(),
+                    0,
+                )
+            };
+            if ret < 0 {
+                return Err(crate::Error::AVError(format!(
+                    "Failed to set encoder opt `{}` to `{}`",
+                    opt_k, opt_v
+                )));
+            }
+        }
+
+        let pix_fmt_name = CString::new(config.output_pix_fmt.clone()).unwrap();
+        let output_pix_fmt = unsafe { ffi::av_get_pix_fmt(pix_fmt_name.as_ptr()) };
+        if output_pix_fmt == ffi::AVPixelFormat_AV_PIX_FMT_NONE {
+            return Err(crate::Error::ConfigError(format!(
+                "Failed to find output pix fmt `{}`",
+                config.output_pix_fmt
+            )));
+        }
+
+        // If supported pix_fmts are known make sure the output pix_fmt is supported
+        if !codec.pix_fmts.is_null() {
+            let mut found = false;
+            for i in 0.. {
+                let pix_fmt = unsafe { *codec.pix_fmts.add(i) };
+                if pix_fmt == -1 {
+                    break;
+                }
+                if pix_fmt == output_pix_fmt {
+                    found = true;
+                    break;
+                }
+            }
+            if !found {
+                return Err(crate::Error::ConfigError(format!(
+                    "Output pix_fmt `{}` not supported by encoder",
+                    config.output_pix_fmt
+                )));
+            }
+        }
+
+        let av_time_base = crate::util::rat_to_avrat(time_base);
+        unsafe {
+            (*codec_ctx).height = config.output_height as i32;
+            (*codec_ctx).width = config.output_width as i32;
+            (*codec_ctx).time_base = av_time_base;
+            (*codec_ctx).gop_size = 10; // TODO: Don't set?
+            (*codec_ctx).pix_fmt = output_pix_fmt;
+            (*codec_ctx).flags |= ffi::AV_CODEC_FLAG_GLOBAL_HEADER as i32;
+        }
+
+        if unsafe { ffi::avcodec_open2(codec_ctx, codec, ptr::null_mut()) } < 0 {
+            return Err(crate::Error::AVError("Failed to open encoder".to_string()));
+        }
+
+        let packet = unsafe { ffi::av_packet_alloc() };
+        if packet.is_null() {
+            return Err(crate::Error::AVError(
+                "Failed to allocate packet".to_string(),
+            ));
+        }
+
+        Ok(Encoder {
+            codec_ctx,
+            packet,
+            time_base: *time_base,
+            flushed: false,
+        })
+    }
+
+    pub(crate) fn encode(&mut self, pts: &Rational64, frame: &AVFrame) -> Result<(), crate::Error> {
+        // TODO: Do this elsewhere?
+        if unsafe { ffi::av_frame_make_writable(frame.inner) } < 0 {
+            return Err(crate::Error::AVError(
+                "Failed to make frame writable".to_string(),
+            ));
+        }
+        unsafe {
+            // It's none of our business what the input frame type is
+            // Also, we don't want the encoder to complain if something looks weird
+            (*frame.inner).pict_type = ffi::AVPictureType_AV_PICTURE_TYPE_NONE;
+        }
+
+        let time_scaled = pts / self.time_base;
+        assert!(*time_scaled.denom() == 1);
+        debug!("ENCODE - Set packet pts to {}", *time_scaled.numer());
+        unsafe {
+            (*frame.inner).pts = *time_scaled.numer();
+            (*frame.inner).pkt_dts = 0;
+        }
+
+        let ret = unsafe { ffi::avcodec_send_frame(self.codec_ctx, frame.inner) };
+        if ret < 0 {
+            let error = ffi::av_err2str(ret);
+            return Err(crate::Error::AVError(format!(
+                "Failed to send frame to encoder: {}",
+                error
+            )));
+        }
+
+        Ok(())
+    }
+
+    pub(crate) fn flush(&mut self) -> Result<(), crate::Error> {
+        assert!(!self.flushed);
+        self.flushed = true;
+        if unsafe { ffi::avcodec_send_frame(self.codec_ctx, ptr::null_mut()) } < 0 {
+            return Err(crate::Error::AVError("Failed to flush encoder".to_string()));
+        }
+
+        Ok(())
+    }
+
+    pub(crate) fn get_packet(&mut self) -> Option<*mut ffi::AVPacket> {
+        if unsafe { ffi::avcodec_receive_packet(self.codec_ctx, self.packet) } >= 0 {
+            Some(self.packet)
+        } else {
+            None
+        }
+    }
+
+    pub(crate) fn close(&mut self) {
+        assert!(self.flushed);
+        assert!(self.get_packet().is_none());
+
+        info!("Closing encoder");
+        unsafe {
+            ffi::av_packet_free(&mut self.packet);
+            ffi::avcodec_free_context(&mut self.codec_ctx);
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/av/framesource.rs.html b/src/vidformer/av/framesource.rs.html new file mode 100644 index 0000000..6c7e956 --- /dev/null +++ b/src/vidformer/av/framesource.rs.html @@ -0,0 +1,307 @@ +framesource.rs - source

vidformer/av/
framesource.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
use num::Zero;
+use num_rational::Rational64;
+use rusty_ffmpeg::ffi;
+
+use crate::av::decoder::Decoder;
+use crate::av::demuxer::Demuxer;
+
+pub struct FrameSource {
+    demuxer: Demuxer,
+    decoder: Decoder,
+    packet: *mut ffi::AVPacket,
+    pub frame: *mut ffi::AVFrame,
+    frames_needs_unref: bool,
+}
+
+impl FrameSource {
+    pub fn new(
+        vid_path: &str,
+        stream: usize,
+        seek_ts: &Rational64,
+        service: &crate::service::Service,
+        file_size: u64,
+        io_runtime_handle: &tokio::runtime::Handle,
+    ) -> Result<FrameSource, crate::Error> {
+        let mut demuxer = crate::av::demuxer::Demuxer::new(
+            vid_path,
+            stream,
+            service,
+            file_size,
+            io_runtime_handle,
+        )?;
+        if !seek_ts.is_zero() {
+            demuxer.seek(seek_ts)?;
+        }
+
+        let decoder = crate::av::decoder::Decoder::new(demuxer.codec, demuxer.codec_parameters)?;
+
+        let frame = unsafe { ffi::av_frame_alloc().as_mut() }
+            .expect("failed to allocate memory for AVFrame");
+        let packet = unsafe { ffi::av_packet_alloc().as_mut() }
+            .expect("failed to allocate memory for AVPacket");
+
+        Ok(FrameSource {
+            demuxer,
+            decoder,
+            packet,
+            frame,
+            frames_needs_unref: false,
+        })
+    }
+
+    pub fn next_frame(&mut self) -> Result<Option<()>, crate::Error> {
+        if self.frames_needs_unref {
+            unsafe {
+                ffi::av_frame_unref(self.frame);
+            }
+            self.frames_needs_unref = false;
+        }
+
+        // Always try to remove ready frames before reading more packets
+        loop {
+            match self.decoder.read_frame(self.frame)? {
+                crate::av::decoder::DecoderResult::Frame => {
+                    // we have a frame, yay!
+                    self.frames_needs_unref = true;
+                    return Ok(Some(()));
+                }
+                crate::av::decoder::DecoderResult::Again => {
+                    // we need more packets
+                    if self.demuxer.read_packet(self.packet).is_some() {
+                        self.decoder.send_packet(self.packet);
+                        unsafe {
+                            ffi::av_packet_unref(self.packet);
+                        }
+                    } else {
+                        // no more packets, flush the decoder and go until EOF
+                        self.decoder.flush();
+                    }
+                }
+                crate::av::decoder::DecoderResult::Eof => {
+                    // we are done
+                    return Ok(None);
+                }
+            }
+        }
+    }
+
+    pub fn time_base(&self) -> &Rational64 {
+        &self.demuxer.time_base
+    }
+
+    pub fn as_avframe(&self) -> std::sync::Arc<crate::dve::AVFrame> {
+        std::sync::Arc::new(crate::dve::AVFrame::clone_avframe(self.frame))
+    }
+}
+
+impl Drop for FrameSource {
+    fn drop(&mut self) {
+        if self.frames_needs_unref {
+            unsafe {
+                ffi::av_frame_unref(self.frame);
+            }
+        }
+        unsafe {
+            ffi::av_frame_free(&mut (self.frame as *mut _));
+            ffi::av_packet_free(&mut (self.packet as *mut _));
+        }
+        self.decoder.close();
+        self.demuxer.close();
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    const TEST_VID: &str = "../tos_720p.mp4";
+    const TEST_STREAM: usize = 0;
+
+    #[test]
+    fn tos_test() {
+        let service = crate::service::Service::default();
+        let profile = crate::source::SourceVideoStreamMeta::profile(
+            "tos_720p",
+            "../tos_720p.mp4",
+            0,
+            &service,
+        )
+        .unwrap();
+
+        let io_runtime = tokio::runtime::Builder::new_multi_thread()
+            .worker_threads(1)
+            .enable_all()
+            .build()
+            .unwrap();
+
+        let mut decoded_frames = 0;
+        let mut framesource = FrameSource::new(
+            TEST_VID,
+            TEST_STREAM,
+            &0.into(),
+            &service,
+            profile.file_size,
+            io_runtime.handle(),
+        )
+        .unwrap();
+
+        while framesource.next_frame().unwrap().is_some() {
+            decoded_frames += 1;
+        }
+
+        assert_eq!(decoded_frames, 17616);
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/av/mod.rs.html b/src/vidformer/av/mod.rs.html new file mode 100644 index 0000000..50cf2b9 --- /dev/null +++ b/src/vidformer/av/mod.rs.html @@ -0,0 +1,11 @@ +mod.rs - source

vidformer/av/
mod.rs

+1
+2
+3
+4
+5
mod decoder;
+pub(crate) mod demuxer;
+pub(crate) mod encoder;
+pub(crate) mod framesource;
+pub(crate) mod muxer;
+
\ No newline at end of file diff --git a/src/vidformer/av/muxer.rs.html b/src/vidformer/av/muxer.rs.html new file mode 100644 index 0000000..ded9202 --- /dev/null +++ b/src/vidformer/av/muxer.rs.html @@ -0,0 +1,311 @@ +muxer.rs - source

vidformer/av/
muxer.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
use log::*;
+use num_rational::Rational64;
+use rusty_ffmpeg::ffi;
+use std::ffi::CString;
+use std::ptr;
+
+pub struct Muxer {
+    pub ofmt_ctx: *mut ffi::AVFormatContext,
+    pub out_time_base: ffi::AVRational,
+    pub out_stream: *mut ffi::AVStream,
+    pub frames: usize,
+}
+
+impl Muxer {
+    pub fn new(
+        output_path: &str,
+        codecpar: *mut ffi::AVCodecParameters,
+        time_base: &Rational64,
+        format_name: Option<&str>,
+    ) -> Result<Self, crate::Error> {
+        let output_path = CString::new(output_path).unwrap();
+        let mut ofmt_ctx: *mut ffi::AVFormatContext = ptr::null_mut();
+
+        let format_name_cstr: Option<CString> = format_name.map(|name| CString::new(name).unwrap());
+
+        if unsafe {
+            ffi::avformat_alloc_output_context2(
+                &mut ofmt_ctx,
+                ptr::null_mut(),
+                format_name_cstr
+                    .as_ref()
+                    .map_or(ptr::null(), |s| s.as_ptr()),
+                output_path.as_ptr(),
+            )
+        } < 0
+        {
+            return Err(crate::Error::AVError(
+                "Failed to allocate output context".to_string(),
+            ));
+        }
+
+        unsafe {
+            (*ofmt_ctx).debug = 1;
+        }
+
+        let out_stream = unsafe { ffi::avformat_new_stream(ofmt_ctx, ptr::null()) };
+        if out_stream.is_null() {
+            return Err(crate::Error::AVError(
+                "Failed to allocate output stream".to_string(),
+            ));
+        }
+
+        let time_base = crate::util::rat_to_avrat(time_base);
+        unsafe {
+            ffi::avcodec_parameters_free(&mut (*out_stream).codecpar); // free existing codec parameters, this is the only reference to them
+
+            (*out_stream).codecpar = ffi::avcodec_parameters_alloc();
+            if (*out_stream).codecpar.is_null() {
+                return Err(crate::Error::AVError(
+                    "Failed to allocate codec parameters".to_string(),
+                ));
+            }
+            if ffi::avcodec_parameters_copy((*out_stream).codecpar, codecpar) < 0 {
+                return Err(crate::Error::AVError(
+                    "Failed to copy codec parameters".to_string(),
+                ));
+            }
+
+            (*out_stream).time_base = time_base;
+        }
+
+        if unsafe { (*(*ofmt_ctx).oformat).flags } & ffi::AVFMT_NOFILE as i32 == 0
+            && unsafe {
+                ffi::avio_open(
+                    &mut (*ofmt_ctx).pb,
+                    output_path.as_ptr(),
+                    ffi::AVIO_FLAG_WRITE as i32,
+                )
+            } < 0
+        {
+            return Err(crate::Error::AVError(
+                "Failed to open output file".to_string(),
+            ));
+        }
+
+        // show output on terminal
+        unsafe {
+            ffi::av_dump_format(ofmt_ctx, 0, output_path.as_ptr(), 1);
+        }
+
+        if unsafe { ffi::avformat_write_header(ofmt_ctx, ptr::null_mut()) } < 0 {
+            return Err(crate::Error::AVError(
+                "Failed to write output container header".to_string(),
+            ));
+        }
+
+        Ok(Muxer {
+            ofmt_ctx,
+            out_time_base: unsafe { (*out_stream).time_base },
+            out_stream,
+            frames: 0,
+        })
+    }
+
+    pub fn mux_packet(&mut self, packet: *mut ffi::AVPacket) -> Result<(), crate::Error> {
+        let input_pts = unsafe { (*packet).pts };
+        let input_dts = unsafe { (*packet).dts };
+
+        unsafe {
+            (*packet).pos = -1;
+            (*packet).stream_index = (*self.out_stream).index;
+            (*packet).duration = 0;
+        }
+
+        info!(
+            "MUX - Write packet with pts {} and dts {} side_elements={} flags={} (output pts = {}/{} and dts = {}/{})",
+            input_pts,
+            input_dts,
+            unsafe { (*packet).side_data_elems },
+            unsafe { (*packet).flags },
+            unsafe { (*packet).pts },
+            unsafe { (*self.out_stream).time_base.den},
+            unsafe { (*packet).dts },
+            unsafe { (*self.out_stream).time_base.den},
+        );
+
+        // Todo: maybe optionally interleave?
+        if unsafe { ffi::av_interleaved_write_frame(self.ofmt_ctx, packet) } < 0 {
+            return Err(crate::Error::AVError(
+                "Failed to write packet to output".to_string(),
+            ));
+        }
+
+        self.frames += 1;
+
+        Ok(())
+    }
+
+    pub fn close(self) -> Result<(), crate::Error> {
+        info!("Closing muxer");
+
+        // flush
+        if unsafe { ffi::av_interleaved_write_frame(self.ofmt_ctx, ptr::null_mut()) } < 0 {
+            return Err(crate::Error::AVError("Failed to flush output".to_string()));
+        }
+
+        unsafe {
+            ffi::av_write_trailer(self.ofmt_ctx);
+            ffi::avio_close((*self.ofmt_ctx).pb);
+            ffi::avformat_free_context(self.ofmt_ctx);
+        }
+
+        Ok(())
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/dve.rs.html b/src/vidformer/dve.rs.html new file mode 100644 index 0000000..ebf05af --- /dev/null +++ b/src/vidformer/dve.rs.html @@ -0,0 +1,2727 @@ +dve.rs - source

vidformer/
dve.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
+967
+968
+969
+970
+971
+972
+973
+974
+975
+976
+977
+978
+979
+980
+981
+982
+983
+984
+985
+986
+987
+988
+989
+990
+991
+992
+993
+994
+995
+996
+997
+998
+999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
use crate::av;
+use crate::filter;
+use crate::filter::Frame;
+use crate::pool::Pool;
+use crate::sir;
+
+use crate::spec::Spec;
+use crate::util;
+use log::*;
+use num::integer::Roots;
+use num_rational::Rational64;
+use parking_lot::Condvar;
+use parking_lot::Mutex;
+use rusty_ffmpeg::ffi;
+use serde::Deserialize;
+use serde::Serialize;
+use std::collections::BTreeMap;
+use std::collections::BTreeSet;
+use std::ffi::CString;
+use std::sync::atomic::AtomicI64;
+use std::sync::atomic::Ordering;
+use std::sync::Arc;
+
+#[derive(thiserror::Error, Debug)]
+pub enum Error {
+    #[error("Source `{0}` not found")]
+    SourceNotFound(String),
+    #[error("Index `{1:?}` out of bounds on source `{0}`")]
+    IndexOutOfBounds(String, sir::IndexConst),
+    #[error("Missing filter arg")]
+    MissingFilterArg,
+    #[error("Invalid filter arg type on `{0}`. Expected `{1}`, got `{2}`")]
+    InvalidFilterArgType(String, String, String),
+    #[error("Invalid filter arg value `{0}`: `{1}`")]
+    InvalidFilterArgValue(String, String),
+    #[error("Filter internal error: {0}")]
+    FilterInternalError(String),
+    #[error("Invalid output frame type")]
+    InvalidOutputFrameType,
+    #[error("Config error: {0}")]
+    ConfigError(String),
+    #[error("AV error: {0}")]
+    AVError(String),
+    #[error("IO error: {0}")]
+    IOError(String),
+    #[error("Unknown error: {0}")]
+    Unknown(String),
+}
+
+#[derive(Ord, Eq, PartialEq, PartialOrd, Clone, Debug)]
+pub(crate) struct SourceRef {
+    video: String,
+}
+
+impl SourceRef {
+    pub fn new(video: &str) -> Self {
+        SourceRef {
+            video: video.to_string(),
+        }
+    }
+}
+
+impl std::fmt::Display for SourceRef {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.video)
+    }
+}
+
+/// A context for a spec
+///
+/// This is a collection of sources, filters, and arrays that are used to execute a DVE spec.
+/// It's a pretty simple layout here, but if you really want to incorporate vidformer deep into a VDBMS, you
+/// gut this object and make the sources and arrays backed directly through your DB.
+pub struct Context {
+    pub(crate) sources: BTreeMap<SourceRef, crate::source::SourceVideoStreamMeta>,
+    pub(crate) filters: BTreeMap<String, Box<dyn crate::filter::Filter>>,
+    pub(crate) arrays: BTreeMap<String, Box<dyn crate::array::Array>>,
+}
+
+#[derive(Debug)]
+
+pub(crate) struct AVFrame {
+    pub(crate) inner: *mut ffi::AVFrame,
+}
+
+impl AVFrame {
+    pub(crate) fn clone_avframe(frame: *mut ffi::AVFrame) -> AVFrame {
+        let new_frame = unsafe { ffi::av_frame_clone(frame) };
+        AVFrame { inner: new_frame }
+    }
+}
+
+unsafe impl Send for AVFrame {}
+unsafe impl Sync for AVFrame {}
+
+impl Drop for AVFrame {
+    fn drop(&mut self) {
+        unsafe { ffi::av_frame_free(&mut self.inner) }
+    }
+}
+
+pub(crate) struct EmptySpecCtx;
+impl crate::spec::SpecContext for EmptySpecCtx {}
+
+impl Context {
+    pub fn new(
+        source_files: Vec<crate::source::SourceVideoStreamMeta>,
+        arrays: BTreeMap<String, Box<dyn crate::array::Array>>,
+        filters: BTreeMap<String, Box<dyn crate::filter::Filter>>,
+    ) -> Context {
+        let mut sources = BTreeMap::new();
+        for source in source_files {
+            sources.insert(SourceRef::new(&source.name), source);
+        }
+        Context {
+            sources,
+            arrays,
+            filters,
+        }
+    }
+
+    pub fn spec_ctx(&self) -> impl crate::spec::SpecContext {
+        EmptySpecCtx
+    }
+
+    pub(crate) fn get_gop_frames(
+        &self,
+        source: &SourceRef,
+        gop_idx: usize,
+    ) -> BTreeSet<Rational64> {
+        let stream_meta = &self.sources.get(source).unwrap();
+        let mut out = BTreeSet::new();
+
+        let gop_start_ts = stream_meta.keys[gop_idx];
+        let next_gop_start_ts = if gop_idx >= stream_meta.keys.len() - 1 {
+            None
+        } else {
+            Some(stream_meta.keys[gop_idx + 1])
+        };
+
+        // TODO: Use binary search to speed up
+        for frame_ts in &stream_meta.ts {
+            if frame_ts >= &gop_start_ts {
+                if next_gop_start_ts.is_some() && frame_ts >= next_gop_start_ts.as_ref().unwrap() {
+                    break;
+                }
+                out.insert(*frame_ts);
+            }
+        }
+
+        out
+    }
+
+    pub(crate) fn resolve_frame_source(
+        &self,
+        frame_source: &crate::sir::FrameSource,
+    ) -> Result<(SourceRef, Rational64), Error> {
+        let source_name: &String = &frame_source.video;
+        let sourceref = SourceRef::new(source_name);
+        if let Some(source) = self.sources.get(&sourceref) {
+            match &frame_source.index {
+                crate::sir::IndexConst::T(t) => {
+                    // make sure the timestamp exists
+                    match source.ts.binary_search(t) {
+                        Ok(_) => Ok((sourceref, *t)),
+                        Err(_) => Err(Error::IndexOutOfBounds(
+                            source_name.clone(),
+                            frame_source.index.clone(),
+                        )),
+                    }
+                }
+                crate::sir::IndexConst::ILoc(k) => {
+                    if let Some(t) = source.ts.get(*k) {
+                        Ok((SourceRef::new(&frame_source.video), *t))
+                    } else {
+                        Err(Error::IndexOutOfBounds(
+                            source_name.clone(),
+                            frame_source.index.clone(),
+                        ))
+                    }
+                }
+            }
+        } else {
+            Err(Error::SourceNotFound(source_name.clone()))
+        }
+    }
+}
+
+#[derive(Debug)]
+pub(crate) struct DecoderState {
+    pub source: SourceRef,
+    pub gop_idx: usize,
+    pub future_frames: BTreeSet<Rational64>,
+    pub past_frames: BTreeSet<Rational64>,
+}
+
+impl DecoderState {
+    pub(crate) fn future_iframerefs(&self) -> BTreeSet<IFrameRef> {
+        self.future_frames
+            .iter()
+            .map(|t| IFrameRef {
+                sourceref: self.source.clone(),
+                pts: *t,
+            })
+            .collect()
+    }
+}
+
+pub(crate) fn run_decoder(
+    context: &Context,
+    stat: &StatRunner,
+    source: &SourceRef,
+    gop_idx: usize,
+    pool: &Arc<(Mutex<Pool>, Condvar)>,
+    decoder_id: String,
+    io_runtime_handle: &tokio::runtime::Handle,
+) -> Result<(), Error> {
+    let stream_meta = &context.sources.get(source).unwrap();
+    let stream_service = &stream_meta.service;
+
+    let mut framesource = av::framesource::FrameSource::new(
+        &stream_meta.file_path,
+        stream_meta.stream_idx,
+        &stream_meta.keys[gop_idx],
+        stream_service,
+        stream_meta.file_size,
+        io_runtime_handle,
+    )?;
+
+    while framesource.next_frame()?.is_some() {
+        stat.frames_decoded
+            .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
+        unsafe {
+            debug!(
+                "DECODE - Frame (type={}, size={} bytes, pts={} key_frame={})",
+                char::from(ffi::av_get_picture_type_char((*framesource.frame).pict_type) as u8),
+                (*framesource.frame).pkt_size,
+                (*framesource.frame).pts,
+                (*framesource.frame).key_frame,
+            );
+        }
+        let frame_t =
+            Rational64::new(unsafe { (*framesource.frame).pts }, 1) * framesource.time_base();
+        let iframeref = IFrameRef {
+            sourceref: source.clone(),
+            pts: frame_t,
+        };
+
+        loop {
+            let mut pool_ref = pool.0.lock();
+            if pool_ref.terminate_decoders {
+                return Ok(());
+            }
+
+            {
+                let decoder_state = pool_ref.decoders.get_mut(&decoder_id).unwrap();
+                debug_assert!(decoder_state.source == *source);
+                debug_assert!(decoder_state.gop_idx == gop_idx);
+
+                if !decoder_state.future_frames.contains(&iframeref.pts) {
+                    warn!(
+                        "Decoded frame pts={} not extected in {}:gop{}",
+                        iframeref.pts, source, gop_idx
+                    );
+                    return Err(Error::AVError(format!(
+                        "Decoded frame not expected, source {} gop {} not encoded correctly!",
+                        source, gop_idx
+                    )));
+                }
+            }
+
+            if pool_ref.should_stall(&decoder_id) {
+                if pool_ref.should_decoder_abandon(&decoder_id) {
+                    pool_ref.decoders.remove(&decoder_id);
+                    pool_ref
+                        .finished_unjoined_decoders
+                        .insert(decoder_id.clone());
+                    pool.1.notify_all();
+                    return Ok(());
+                } else {
+                    pool.1.wait(&mut pool_ref);
+                    continue;
+                }
+            }
+
+            let avframe = framesource.as_avframe();
+            debug!("Adding frame {}:{} to pool", source, iframeref.pts);
+            pool_ref.decoded(&decoder_id, iframeref.clone(), avframe);
+
+            let decoder_state = pool_ref.decoders.get_mut(&decoder_id).unwrap();
+            decoder_state.future_frames.remove(&iframeref.pts);
+            decoder_state.past_frames.insert(iframeref.pts);
+
+            // we've mutated the pool
+            pool.1.notify_all();
+
+            if decoder_state.future_frames.is_empty() {
+                pool_ref.decoders.remove(&decoder_id);
+                pool_ref
+                    .finished_unjoined_decoders
+                    .insert(decoder_id.clone());
+                return Ok(());
+            } else {
+                break;
+            }
+        }
+    }
+
+    Err(Error::AVError("Decoder ran out of frames".to_string()))
+}
+
+struct FilterTask {
+    gen: usize,
+    oframe_expr: crate::sir::FrameExpr,
+    dep_frames: BTreeMap<IFrameRef, Arc<AVFrame>>,
+}
+
+struct FilterTaskResult {
+    gen: usize,
+    oframe: Arc<AVFrame>,
+}
+
+fn run_filter(
+    context: &Context,
+    config: &Config,
+    _stat: &StatRunner,
+    input_channel: crossbeam_channel::Receiver<Option<FilterTask>>,
+    output_channel: crossbeam_channel::Sender<FilterTaskResult>,
+) -> Result<(), Error> {
+    loop {
+        match input_channel.recv() {
+            Ok(Some(filter_task)) => {
+                debug!("Filtering gen {}", filter_task.gen);
+                let oframe = render_frame(
+                    context,
+                    config,
+                    &filter_task.oframe_expr,
+                    &filter_task.dep_frames,
+                )?;
+
+                let result = FilterTaskResult {
+                    gen: filter_task.gen,
+                    oframe,
+                };
+
+                output_channel.send(result).unwrap();
+            }
+            Ok(None) => {
+                debug!("Filter recieved kill signal");
+                return Ok(());
+            }
+            Err(crossbeam_channel::RecvError) => {
+                return Err(Error::Unknown("Filter channel closed".to_string()));
+            }
+        }
+    }
+}
+
+#[derive(Ord, Eq, PartialEq, PartialOrd, Clone, Debug)]
+pub struct IFrameRef {
+    pub sourceref: SourceRef,
+    pub pts: Rational64,
+}
+
+/// Config for a spesific run of a vidformer spec
+///
+/// This is a collection of settings that are used to execute a spec.
+/// This combines information about the output with internal performance knobs.
+///
+/// The max number of frames in memory is roughly decoders + decode_pool_size + decoder_view
+#[derive(Debug, Deserialize, Serialize, Clone)]
+pub struct Config {
+    /// The number of frames which can be fit in the decode pool
+    pub decode_pool_size: usize,
+    /// How many output frames can be active at once
+    /// This also limits how many frames can be in the filters + encode buffer at once
+    pub decoder_view: usize,
+    /// How many decoders can be active at once
+    pub decoders: usize,
+    /// How many filter threads to run
+    pub filterers: usize,
+
+    pub output_width: usize,
+    pub output_height: usize,
+    pub output_pix_fmt: String, // needs to be an AVPixelFormat
+
+    /// Configuration to use for output encoder
+    pub encoder: Option<EncoderConfig>,
+
+    /// The name of the format to use for output.
+    /// If None, the format will be inferred from the output path.
+    pub format: Option<String>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct EncoderConfig {
+    pub codec_name: String,
+
+    pub opts: Vec<(String, String)>,
+}
+
+impl EncoderConfig {
+    pub(crate) fn avcodec(&self) -> Result<&'static ffi::AVCodec, Error> {
+        let codec_name = &self.codec_name;
+        let codec_name_cstr = CString::new(codec_name.clone()).unwrap();
+
+        let av_codec =
+            unsafe { ffi::avcodec_find_encoder_by_name(codec_name_cstr.as_ptr()).as_ref() };
+        match av_codec {
+            Some(av_codec) => Ok(av_codec),
+            None => Err(Error::ConfigError(format!(
+                "Failed to find encoder for `{}` codec",
+                codec_name
+            ))),
+        }
+    }
+}
+
+impl Config {
+    pub(crate) fn expected_output_type(&self) -> filter::FrameType {
+        filter::FrameType {
+            width: self.output_width,
+            height: self.output_height,
+            format: util::pixel_fmt_str_to_av_pix_fmt(self.output_pix_fmt.as_str()).unwrap(),
+        }
+    }
+}
+
+/// Stats from a run of a vidformer spec
+#[derive(Debug, Serialize)]
+pub struct Stats {
+    pub max_decoder_count: usize,
+    pub max_encode_buffer_size: usize,
+    pub decoders_created: usize,
+    pub frames_written: usize,
+    pub frames_decoded: usize,
+    pub runtime: std::time::Duration,
+}
+
+pub(crate) struct StatRunner {
+    max_decoder_count: std::sync::atomic::AtomicUsize,
+    max_encode_buffer_size: std::sync::atomic::AtomicUsize,
+    decoders_created: std::sync::atomic::AtomicUsize,
+    frames_written: std::sync::atomic::AtomicUsize,
+    frames_decoded: std::sync::atomic::AtomicUsize,
+    start_time: std::time::Instant,
+}
+
+impl StatRunner {
+    fn new() -> Self {
+        StatRunner {
+            max_decoder_count: std::sync::atomic::AtomicUsize::new(0),
+            max_encode_buffer_size: std::sync::atomic::AtomicUsize::new(0),
+            decoders_created: std::sync::atomic::AtomicUsize::new(0),
+            frames_written: std::sync::atomic::AtomicUsize::new(0),
+            frames_decoded: std::sync::atomic::AtomicUsize::new(0),
+            start_time: std::time::Instant::now(),
+        }
+    }
+
+    fn stats(&self) -> Stats {
+        Stats {
+            max_decoder_count: self
+                .max_decoder_count
+                .load(std::sync::atomic::Ordering::SeqCst),
+            max_encode_buffer_size: self
+                .max_encode_buffer_size
+                .load(std::sync::atomic::Ordering::SeqCst),
+            decoders_created: self
+                .decoders_created
+                .load(std::sync::atomic::Ordering::SeqCst),
+            frames_written: self
+                .frames_written
+                .load(std::sync::atomic::Ordering::SeqCst),
+            frames_decoded: self
+                .frames_decoded
+                .load(std::sync::atomic::Ordering::SeqCst),
+            runtime: std::time::Instant::now() - self.start_time,
+        }
+    }
+}
+
+pub(crate) fn type_frame(
+    context: &Context,
+    _config: &Config,
+    frame: &crate::sir::FrameExpr,
+) -> Result<filter::FrameType, Error> {
+    match frame {
+        crate::sir::FrameExpr::Source(s) => {
+            let (sourceref, _t) = context.resolve_frame_source(s)?;
+            let source = context.sources.get(&sourceref).unwrap();
+            Ok(filter::FrameType {
+                width: source.resolution.0,
+                height: source.resolution.1,
+                format: util::pixel_fmt_str_to_av_pix_fmt(source.pix_fmt.as_str()).unwrap(),
+            })
+        }
+        crate::sir::FrameExpr::Filter(f) => {
+            let filter = context.filters.get(&f.name);
+
+            if filter.is_none() {
+                return Err(Error::Unknown(format!("Filter `{}` not found", f.name)));
+            }
+            let filter = filter.unwrap();
+
+            let mut args = Vec::new();
+            let mut kwargs = BTreeMap::new();
+
+            for arg in &f.args {
+                match arg {
+                    crate::sir::Expr::Frame(frame) => {
+                        let frame = type_frame(context, _config, frame)?;
+                        args.push(filter::Val::FrameType(frame));
+                    }
+                    crate::sir::Expr::Data(data) => {
+                        args.push(crate::filter::Val::from_expr(data, context));
+                    }
+                }
+            }
+            for (k, v) in &f.kwargs {
+                match v {
+                    crate::sir::Expr::Frame(frame) => {
+                        let frame = type_frame(context, _config, frame)?;
+                        kwargs.insert(k.clone(), filter::Val::FrameType(frame));
+                    }
+                    crate::sir::Expr::Data(data) => {
+                        kwargs.insert(k.clone(), crate::filter::Val::from_expr(data, context));
+                    }
+                }
+            }
+
+            Ok(filter.filter_type(&args, &kwargs)?)
+        }
+    }
+}
+
+fn render_frame(
+    context: &Context,
+    _config: &Config,
+    frame: &crate::sir::FrameExpr,
+    loaded_frames: &BTreeMap<IFrameRef, Arc<AVFrame>>,
+) -> Result<Arc<AVFrame>, Error> {
+    info!("Rendering frame {}", frame);
+    match frame {
+        crate::sir::FrameExpr::Source(s) => {
+            let (source_ref, t) = context.resolve_frame_source(s)?;
+            let frame_ref = IFrameRef {
+                sourceref: source_ref,
+                pts: t,
+            };
+            let frame = loaded_frames.get(&frame_ref).unwrap();
+            Ok(frame.clone())
+        }
+        crate::sir::FrameExpr::Filter(f) => {
+            let filter = context.filters.get(&f.name).unwrap();
+            let mut args = Vec::new();
+            let mut kwargs = BTreeMap::new();
+
+            // TODO: Very easy to parallelize these two loops
+            for arg in &f.args {
+                match arg {
+                    crate::sir::Expr::Frame(frame) => {
+                        let frame = render_frame(context, _config, frame, loaded_frames)?;
+                        args.push(crate::filter::Val::Frame(Frame::new_arc(frame)));
+                    }
+                    crate::sir::Expr::Data(data) => {
+                        args.push(crate::filter::Val::from_expr(data, context));
+                    }
+                }
+            }
+            for (k, v) in &f.kwargs {
+                match v {
+                    crate::sir::Expr::Frame(frame) => {
+                        let frame = render_frame(context, _config, frame, loaded_frames)?;
+                        kwargs.insert(k.clone(), crate::filter::Val::Frame(Frame::new_arc(frame)));
+                    }
+                    crate::sir::Expr::Data(data) => {
+                        kwargs.insert(k.clone(), crate::filter::Val::from_expr(data, context));
+                    }
+                }
+            }
+
+            let oframe = filter.filter(&args, &kwargs)?;
+
+            Ok(oframe.into_avframe())
+        }
+    }
+}
+
+/// Select whether the output timestamps are local to the ranged segment or the entire output
+///
+/// - `SegmentLocal`: The output timestamps are in the same timebase as the ranged segment. Used for VOD.
+/// - `StreamLocal`: The output timestamps are in the same timebase as the entire output.
+#[derive(Clone)]
+pub enum RangeTsFormat {
+    SegmentLocal,
+    StreamLocal,
+}
+
+/// A range spesifier
+///
+/// `start` and `end` are the start and end of the range in the timebase of the input, inclusive.
+#[derive(Clone)]
+pub struct Range {
+    pub start: Rational64,
+    pub end: Rational64,
+    pub ts_format: RangeTsFormat,
+}
+
+struct EncodeBuffer {
+    members: Vec<(usize, Arc<AVFrame>)>,
+    terminate_encoder: bool,
+}
+
+impl EncodeBuffer {
+    fn new() -> Self {
+        EncodeBuffer {
+            members: Vec::new(),
+            terminate_encoder: false,
+        }
+    }
+}
+
+struct ExecContext {
+    output_path: String,
+    context: Arc<Context>,
+    config: Arc<Config>,
+
+    stat: Arc<StatRunner>,
+    process_span: Arc<sir::ProcessSpan>,
+
+    pool: Arc<(Mutex<Pool>, Condvar)>,
+    output_time_base: num_rational::Ratio<i64>,
+
+    to_filter_channel: (
+        crossbeam_channel::Sender<Option<FilterTask>>,
+        crossbeam_channel::Receiver<Option<FilterTask>>,
+    ),
+    from_filter_channel: (
+        crossbeam_channel::Sender<FilterTaskResult>,
+        crossbeam_channel::Receiver<FilterTaskResult>,
+    ),
+
+    decoder_count: Arc<AtomicI64>,
+    io_runtime: tokio::runtime::Runtime,
+
+    filtering_gens: BTreeSet<usize>,
+    frames_post_filtering: usize,
+
+    encode_buffer: Arc<(Mutex<EncodeBuffer>, Condvar)>,
+    dec_join_handles: BTreeMap<String, std::thread::JoinHandle<Result<(), Error>>>,
+    filter_join_handles: Vec<std::thread::JoinHandle<Result<(), Error>>>,
+}
+
+impl ExecContext {
+    fn run(mut self) -> Result<Stats, Error> {
+        let enc_thread = {
+            let encode_buffer = self.encode_buffer.clone();
+            let output_path = self.output_path.to_string();
+            let config = self.config.clone();
+            let process_span = self.process_span.clone();
+            let stat = self.stat.clone();
+            let output_time_base = self.output_time_base;
+
+            std::thread::spawn(move || {
+                let r = encoder_thread(
+                    config,
+                    stat,
+                    output_time_base,
+                    output_path,
+                    process_span,
+                    encode_buffer,
+                );
+
+                debug!("Enc thread ended");
+                r
+            })
+        };
+
+        for _i in 0..self.config.filterers {
+            let context = self.context.clone();
+            let config = self.config.clone();
+            let stat = self.stat.clone();
+            let reciever = self.to_filter_channel.1.clone();
+            let sender = self.from_filter_channel.0.clone();
+            let filter_thread =
+                std::thread::spawn(move || run_filter(&context, &config, &stat, reciever, sender));
+            self.filter_join_handles.push(filter_thread);
+        }
+
+        let mut return_err: Option<Error> = Option::None;
+
+        'control_loop: loop {
+            debug_assert!(return_err.is_none());
+
+            // Create new decoders
+            let r = self.create_new_decoders();
+            if let Err(e) = r {
+                return_err = Some(e);
+                break 'control_loop;
+            }
+
+            // Join finished decoders
+            let r = self.join_finished_decoders();
+            match r {
+                Ok(request_early_stop) if request_early_stop => break,
+                Ok(_) => {}
+                Err(e) => {
+                    return_err = Some(e);
+                    break 'control_loop;
+                }
+            }
+            // Create filters
+            let r = self.send_to_filters();
+            if let Err(e) = r {
+                return_err = Some(e);
+                break 'control_loop;
+            }
+
+            // Process filtered frames
+            let r = self.recieve_filtered_frames();
+            if let Err(e) = r {
+                return_err = Some(e);
+                break 'control_loop;
+            }
+
+            // Check if encoder finished
+            {
+                if enc_thread.is_finished() {
+                    // This means the encoder had an error and we should stop
+                    break;
+                }
+            }
+
+            // Check if any filter threads panicked
+            {
+                let finished_i = self
+                    .filter_join_handles
+                    .iter()
+                    .position(|h| h.is_finished());
+                // for filter_join_handle in self.filter_join_handles.iter() {
+                //     if filter_join_handle.is_finished() {
+                //         return_err = Some(Error::Unknown("Filter thread panicked".to_string()));
+                //         break 'control_loop;
+                //     }
+                // }
+                if let Some(finished_i) = finished_i {
+                    let thread_return = self.filter_join_handles.remove(finished_i).join();
+
+                    match thread_return {
+                        Ok(Ok(_)) => {
+                            return_err =
+                                Some(Error::Unknown("Filter thread finished early?".to_string()));
+                            break 'control_loop;
+                        }
+                        Ok(Err(e)) => {
+                            return_err = Some(e);
+                            break 'control_loop;
+                        }
+                        Err(e) => {
+                            return_err = Some(Error::Unknown(format!(
+                                "Filter thread {} panicked: {:?}",
+                                finished_i, e
+                            )));
+                            break 'control_loop;
+                        }
+                    }
+                }
+            }
+
+            if self.frames_post_filtering == self.process_span.frames.len() {
+                break;
+            }
+
+            std::thread::sleep(std::time::Duration::from_micros(250));
+        }
+
+        // If we are here either all frames have been filtered or we have an error
+        debug!("Main exec loop finished");
+
+        // Wait for all decoders to finish
+        {
+            let mut pool_ref = self.pool.0.lock();
+            pool_ref.terminate_decoders = true;
+            self.pool.1.notify_all();
+        }
+
+        while let Some((_decoder_id, dec_join_handle)) = self.dec_join_handles.pop_first() {
+            match dec_join_handle.join() {
+                Ok(decoder_result) => {
+                    match decoder_result {
+                        Ok(_) => {} // Thread finished successfully
+                        Err(e) => {
+                            if return_err.is_none() {
+                                return_err = Some(e);
+                            }
+                        }
+                    }
+                }
+                Err(e) => {
+                    if return_err.is_none() {
+                        return_err =
+                            Some(Error::Unknown(format!("Decoder thread panicked: {:?}", e)));
+                    }
+                    break;
+                }
+            }
+        }
+        debug!("All decoders finished");
+
+        // Wait for all filters to finish
+        for _i in 0..self.config.filterers {
+            self.to_filter_channel.0.send(None).unwrap();
+        }
+        while let Some(filter_join_handle) = self.filter_join_handles.pop() {
+            match filter_join_handle.join() {
+                Ok(filter_result) => {
+                    match filter_result {
+                        Ok(_) => {} // Thread finished successfully
+                        Err(e) => {
+                            if return_err.is_none() {
+                                return_err = Some(e);
+                            }
+                        }
+                    }
+                }
+                Err(e) => {
+                    if return_err.is_none() {
+                        return_err =
+                            Some(Error::Unknown(format!("Filter thread panicked: {:?}", e)));
+                    }
+                    break;
+                }
+            }
+        }
+        debug!("All filters finished");
+
+        // Wait for encoder to finish
+        if return_err.is_some() {
+            let mut encode_buffer_ref = self.encode_buffer.0.lock();
+            // If we have an error kill the encoder now
+            encode_buffer_ref.terminate_encoder = true;
+            self.encode_buffer.1.notify_one();
+        }
+        match enc_thread.join() {
+            Ok(enc_result) => {
+                match enc_result {
+                    Ok(_) => {} // Thread finished successfully
+                    Err(e) => {
+                        assert!(return_err.is_none());
+                        return_err = Some(e);
+                    }
+                }
+            }
+            Err(e) => {
+                assert!(return_err.is_none());
+                return_err = Some(Error::Unknown(format!("Encoder thread panicked: {:?}", e)));
+            }
+        }
+        debug!("Encoder finished");
+
+        match return_err {
+            Some(e) => Err(e),
+            None => Ok(self.stat.stats()),
+        }
+    }
+
+    fn recieve_filtered_frames(&mut self) -> Result<(), Error> {
+        loop {
+            match self.from_filter_channel.1.try_recv() {
+                Ok(result) => {
+                    debug!("Recieved gen {} from filter", result.gen);
+                    debug_assert!(self.filtering_gens.contains(&result.gen));
+                    self.filtering_gens.remove(&result.gen);
+
+                    let oframe = result.oframe;
+                    let gen = result.gen;
+
+                    {
+                        let mut pool_ref = self.pool.0.lock();
+                        debug_assert!(pool_ref.is_gen_ready(gen));
+                        pool_ref.finish_gen(gen);
+                        self.pool.1.notify_all();
+                    }
+
+                    {
+                        let mut encode_buffer_ref = self.encode_buffer.0.lock();
+                        encode_buffer_ref.members.push((gen, oframe));
+                        let encode_buffer_size = encode_buffer_ref.members.len();
+                        self.stat
+                            .max_encode_buffer_size
+                            .fetch_max(encode_buffer_size, Ordering::SeqCst);
+
+                        self.encode_buffer.1.notify_one();
+                    }
+
+                    self.frames_post_filtering += 1;
+                }
+                Err(crossbeam_channel::TryRecvError::Empty) => {
+                    return Ok(());
+                }
+                Err(crossbeam_channel::TryRecvError::Disconnected) => {
+                    return Err(Error::Unknown("Filter channel closed".to_string()));
+                }
+            }
+        }
+    }
+
+    fn join_finished_decoders(&mut self) -> Result<bool, Error> {
+        let mut pool_ref = self.pool.0.lock();
+        while let Some(finished_decoder_id) = pool_ref.finished_unjoined_decoders.pop_first() {
+            let dec_join_handle = self.dec_join_handles.remove(&finished_decoder_id).unwrap();
+            match dec_join_handle.join() {
+                Ok(decoder_result) => {
+                    match decoder_result {
+                        Ok(_) => {} // Thread finished successfully
+                        Err(e) => {
+                            return Err(e);
+                        }
+                    }
+                }
+                Err(e) => {
+                    return Err(Error::Unknown(format!("Decoder thread panicked: {:?}", e)));
+                }
+            }
+            self.pool.1.notify_all();
+        }
+
+        // now that we've removed all decoders which reported themselves as finished check for any panicked decoders
+        for (decoder_id, dec_join_handle) in self.dec_join_handles.iter() {
+            if dec_join_handle.is_finished() {
+                info!(
+                    "Found a unexpected finished decoder thread: {:?}",
+                    decoder_id
+                );
+                return Ok(true);
+            }
+        }
+
+        Ok(false)
+    }
+
+    fn create_new_decoders(&mut self) -> Result<(), Error> {
+        if self.decoder_count.load(Ordering::SeqCst) < self.config.decoders as i64 {
+            debug_assert!(self.decoder_count.load(Ordering::SeqCst) >= 0);
+            let mut pool_ref = self.pool.0.lock();
+            let new_decoder = pool_ref.new_decoder_gop();
+            if let Some((sourceref, gop_idx)) = new_decoder {
+                let source = sourceref.clone();
+                let decoder_id = crate::util::rand_uuid();
+                let decooder_id_join_handle_copy = decoder_id.clone();
+                let pool = self.pool.clone();
+                let context = self.context.clone();
+                let stat = self.stat.clone();
+                let io_runtime_handle = self.io_runtime.handle().clone();
+
+                let num_decoders = self.decoder_count.fetch_add(1, Ordering::SeqCst) + 1;
+                stat.max_decoder_count
+                    .fetch_max(num_decoders as usize, Ordering::SeqCst);
+                stat.decoders_created.fetch_add(1, Ordering::SeqCst);
+                let decoder_count = self.decoder_count.clone();
+
+                let decoder_state = DecoderState {
+                    source: source.clone(),
+                    gop_idx,
+                    future_frames: context.get_gop_frames(&source, gop_idx),
+                    past_frames: BTreeSet::new(),
+                };
+                pool_ref.decoders.insert(decoder_id.clone(), decoder_state);
+                self.pool.1.notify_all();
+
+                debug!("Creating decoder {decoder_id} on {source}:gop{gop_idx}");
+
+                let dec_join_handle = std::thread::Builder::new()
+                    .name("decoder".to_string())
+                    .spawn(move || {
+                        let decoder_result = run_decoder(
+                            &context,
+                            &stat,
+                            &source,
+                            gop_idx,
+                            &pool,
+                            decoder_id.clone(),
+                            &io_runtime_handle,
+                        );
+                        // TODO: Handle error
+                        decoder_count.fetch_add(-1, Ordering::SeqCst);
+                        debug!("Decoder {decoder_id} finished");
+                        decoder_result
+                    })
+                    .unwrap();
+
+                self.dec_join_handles
+                    .insert(decooder_id_join_handle_copy, dec_join_handle);
+            }
+        }
+
+        Ok(())
+    }
+
+    fn send_to_filters(&mut self) -> Result<(), Error> {
+        loop {
+            let gen_to_filter = {
+                let mut out = None;
+                let pool_ref = self.pool.0.lock();
+                for active_gen in pool_ref.active_gens() {
+                    if !self.filtering_gens.contains(&active_gen)
+                        && pool_ref.is_gen_ready(active_gen)
+                    {
+                        out = Some(active_gen);
+                        break;
+                    }
+                }
+                out
+            };
+
+            if gen_to_filter.is_none() {
+                break;
+            }
+            let gen_to_filter = gen_to_filter.unwrap();
+            self.filtering_gens.insert(gen_to_filter);
+
+            let frame_deps = {
+                let pool_ref = self.pool.0.lock();
+                pool_ref.get_ready_gen_frames(gen_to_filter)
+            };
+
+            let filter_task = FilterTask {
+                gen: gen_to_filter,
+                oframe_expr: self.process_span.frames[gen_to_filter].clone(),
+                dep_frames: frame_deps,
+            };
+
+            debug!("Sending gen {} to filter", gen_to_filter);
+
+            self.to_filter_channel.0.send(Some(filter_task)).unwrap();
+        }
+
+        Ok(())
+    }
+}
+
+/// Execute a spec, or a range of a spec.
+pub fn run(
+    spec: &Arc<Box<dyn Spec>>,
+    output_path: &str,
+    context: &Arc<Context>,
+    config: &Arc<Config>,
+    range: &Option<Range>,
+) -> Result<Stats, Error> {
+    if config.decoders > u16::MAX as usize {
+        // yes this is arbitrary, but bad things happen if do something like usize::MAX because we track counts with a i64 internally
+        return Err(Error::ConfigError(
+            "Decoders must be less than u16::MAX".to_string(),
+        ));
+    }
+
+    // Make sure the encoder config is valid
+    if let Some(enc_cfg) = &config.encoder {
+        let _avcodec: &ffi::AVCodec = enc_cfg.avcodec()?;
+    }
+
+    let stat = Arc::new(StatRunner::new());
+    let expected_output_type = config.expected_output_type();
+
+    let process_span = Arc::new(crate::sir::ProcessSpan::create(
+        spec.as_ref().as_ref(),
+        context,
+        range,
+    ));
+
+    // Type check frames
+    for oframe in &process_span.frames {
+        let frame_type = type_frame(context, config, oframe)?;
+        if frame_type != expected_output_type {
+            return Err(Error::InvalidOutputFrameType);
+        }
+    }
+
+    let (pool, output_time_base) = build_pool(&process_span, config, context)?;
+
+    let pool = Arc::new((Mutex::new(pool), Condvar::new()));
+
+    let decoder_count = Arc::new(AtomicI64::new(0));
+
+    let filtering_gens: BTreeSet<usize> = BTreeSet::new();
+    let encode_buffer = Arc::new((Mutex::new(EncodeBuffer::new()), Condvar::new()));
+    let dec_join_handles: BTreeMap<String, std::thread::JoinHandle<Result<(), Error>>> =
+        BTreeMap::new();
+    let filter_join_handles: Vec<std::thread::JoinHandle<Result<(), Error>>> = Vec::new();
+
+    let io_runtime = tokio::runtime::Builder::new_multi_thread()
+        .worker_threads(2.max(config.decoders.sqrt())) // guess a good number of threads to use for I/O
+        .enable_all()
+        .build()
+        .unwrap();
+
+    let exec_contex = ExecContext {
+        output_path: output_path.to_string(),
+        context: context.clone(),
+        config: config.clone(),
+        stat: stat.clone(),
+        process_span,
+        pool,
+        output_time_base,
+        to_filter_channel: crossbeam_channel::unbounded(),
+        from_filter_channel: crossbeam_channel::unbounded(),
+        decoder_count,
+        io_runtime,
+        filtering_gens,
+        frames_post_filtering: 0,
+        encode_buffer,
+        dec_join_handles,
+        filter_join_handles,
+    };
+
+    exec_contex.run()
+}
+
+/// Validate that a spec can be run.
+pub fn validate(
+    spec: &Arc<Box<dyn Spec>>,
+    context: &Arc<Context>,
+    config: &Arc<Config>,
+) -> Result<(), Error> {
+    let expected_output_type = config.expected_output_type();
+
+    let process_span = Arc::new(crate::sir::ProcessSpan::create(
+        spec.as_ref().as_ref(),
+        context,
+        &None,
+    ));
+
+    // Type check frames
+    for oframe in &process_span.frames {
+        let frame_type = type_frame(context, config, oframe)?;
+        if frame_type != expected_output_type {
+            return Err(Error::InvalidOutputFrameType);
+        }
+    }
+
+    Ok(())
+}
+
+fn encoder_thread(
+    config: Arc<Config>,
+    stat: Arc<StatRunner>,
+    output_time_base: num_rational::Ratio<i64>,
+    output_path: String,
+    process_span: Arc<sir::ProcessSpan>,
+    encode_buffer: Arc<(Mutex<EncodeBuffer>, Condvar)>,
+) -> Result<(), Error> {
+    let mut encoder = av::encoder::Encoder::new(&config, &output_time_base)?;
+
+    let mut encoder_codec_params = unsafe { ffi::avcodec_parameters_alloc() };
+    // copy from encoder context
+    if unsafe { ffi::avcodec_parameters_from_context(encoder_codec_params, encoder.codec_ctx) } < 0
+    {
+        return Err(Error::AVError(
+            "Encoder failed to copy codec params to codec context".to_string(),
+        ));
+    }
+
+    let mut muxer = av::muxer::Muxer::new(
+        &output_path,
+        encoder_codec_params,
+        &output_time_base,
+        config.format.as_deref(),
+    )?;
+    let muxer_time_base = crate::util::avrat_to_rat(&muxer.out_time_base);
+    let encoder_to_muxer_ts_multiplier: num_rational::Ratio<i64> =
+        encoder.time_base / muxer_time_base;
+
+    if *encoder_to_muxer_ts_multiplier.denom() != 1 {
+        return Err(Error::AVError(format!(
+            "Can't operate with encoder timebase {} and muxer timebase {}. Are you using mkv?",
+            encoder.time_base, muxer_time_base
+        )));
+    }
+
+    let mut oframe_next = 0;
+
+    loop {
+        // Encode frames
+        {
+            if oframe_next >= process_span.frames.len() {
+                break;
+            }
+
+            let mut encode_buffer_ref = encode_buffer.0.lock();
+
+            if encode_buffer_ref.terminate_encoder {
+                break;
+            }
+
+            let target_index = encode_buffer_ref
+                .members
+                .iter()
+                .position(|(gen, _)| *gen == oframe_next);
+
+            if let Some(target_index) = target_index {
+                let (gen, frame) = encode_buffer_ref.members.remove(target_index);
+
+                let pts = match process_span.output_ts_offset {
+                    Some(offset) => process_span.ts[gen] - offset,
+                    None => process_span.ts[gen],
+                };
+                encoder.encode(&pts, &frame)?;
+                oframe_next += 1;
+            } else {
+                encode_buffer.1.wait(&mut encode_buffer_ref);
+                continue;
+            }
+        }
+
+        // Mux frames
+        if let Some(packet) = encoder.get_packet() {
+            unsafe {
+                (*packet).pts *= *encoder_to_muxer_ts_multiplier.numer();
+                (*packet).dts *= *encoder_to_muxer_ts_multiplier.numer();
+            }
+
+            stat.frames_written
+                .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
+            muxer.mux_packet(packet)?;
+        }
+    }
+
+    encoder.flush()?;
+
+    // Mux frames
+    while let Some(packet) = encoder.get_packet() {
+        unsafe {
+            (*packet).pts *= *encoder_to_muxer_ts_multiplier.numer();
+            (*packet).dts *= *encoder_to_muxer_ts_multiplier.numer();
+        }
+
+        stat.frames_written
+            .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
+        muxer.mux_packet(packet)?;
+    }
+
+    encoder.close();
+    muxer.close()?;
+
+    unsafe {
+        ffi::avcodec_parameters_free(&mut encoder_codec_params);
+    }
+
+    Ok(())
+}
+
+fn build_pool(
+    process_span: &sir::ProcessSpan,
+    config: &Arc<Config>,
+    context: &Arc<Context>,
+) -> Result<(Pool, num_rational::Ratio<i64>), Error> {
+    let mut iframes_per_oframe: Vec<BTreeSet<IFrameRef>> =
+        Vec::<BTreeSet<IFrameRef>>::with_capacity(process_span.frames.len());
+    let mut iframe_refs_in_out_idx: BTreeMap<IFrameRef, BTreeSet<usize>> = BTreeMap::new();
+
+    for (oframe_i, oframe) in process_span.frames.iter().enumerate() {
+        let mut frame_deps = std::collections::BTreeSet::new();
+        oframe.add_deps(&mut frame_deps);
+        assert!(
+            frame_deps.len() <= config.decode_pool_size,
+            "OFrame {} has too many dependencies ({}) for decode pool size {}",
+            oframe_i,
+            frame_deps.len(),
+            config.decode_pool_size
+        );
+
+        let mut iframe_refs = BTreeSet::new();
+        for dep in &frame_deps {
+            let (source_ref, t) = context.resolve_frame_source(dep)?;
+
+            let iframe_ref = IFrameRef {
+                sourceref: source_ref.clone(),
+                pts: t,
+            };
+            iframe_refs.insert(iframe_ref.clone());
+
+            iframe_refs_in_out_idx
+                .entry(iframe_ref)
+                .or_default()
+                .insert(oframe_i);
+        }
+        iframes_per_oframe.push(iframe_refs);
+    }
+    debug_assert_eq!(iframes_per_oframe.len(), process_span.frames.len());
+
+    let output_time_base = {
+        let mut lcm = *process_span.ts[0].denom();
+        for t in &process_span.ts {
+            lcm = num::integer::lcm(lcm, *t.denom());
+        }
+        Rational64::new(1, lcm)
+    };
+
+    let pool = crate::pool::Pool::new(
+        iframes_per_oframe,
+        iframe_refs_in_out_idx,
+        context.clone(),
+        config.clone(),
+    )?;
+
+    Ok((pool, output_time_base))
+}
+
+/// Create [HLS](https://en.wikipedia.org/wiki/HTTP_Live_Streaming) artifacts for a spec
+///
+/// * `spec` - The spec to create HLS artifacts for
+/// * `host_prefix` - The prefix to use for the host (e.g., `https://example.com:8000`)
+/// * `context` - The context to use for the spec
+/// * `config` - The config to use for the spec
+///
+/// Returns a tuple of:
+/// * The namespace for the HLS artifacts
+/// * The text of the m3u8 playlist file
+/// * The text of the m3u8 stream file
+/// * A vector of tuples of the start and end timestamps of each segment
+pub fn create_spec_hls(
+    spec: &dyn Spec,
+    host_prefix: &str,
+    context: &Context,
+    _config: &Config,
+) -> (String, String, String, Vec<(Rational64, Rational64)>) {
+    let namespace = crate::util::rand_uuid().to_string();
+
+    let _playlist_path = format!("{namespace}/playlist.m3u8");
+    let playlist_text = format!(
+        "#EXTM3U\n#EXT-X-STREAM-INF:BANDWIDTH=640000\n{}/{}/stream.m3u8\n",
+        host_prefix, namespace
+    );
+
+    let stream_ts = sir::spec_domain(spec, context);
+    let frame_rate = crate::spec::get_framerate(spec);
+    let segment_duration = 2;
+
+    let mut stream_text = format!("#EXTM3U\n#EXT-X-PLAYLIST-TYPE:VOD\n#EXT-X-TARGETDURATION:{segment_duration}\n#EXT-X-VERSION:4\n#EXT-X-MEDIA-SEQUENCE:0\n");
+    let mut ranges = Vec::new();
+
+    // todo fix off-by-one error
+    for segment_id in 0..=(stream_ts.len() - 1) / (frame_rate * segment_duration) {
+        let stream_ts_path = format!("segment-{segment_id}.ts");
+        stream_text +=
+            &format!("#EXTINF:{segment_duration}.0,\n{host_prefix}/{namespace}/{stream_ts_path}\n");
+
+        let range_start = stream_ts[segment_id * frame_rate * segment_duration];
+        let range_end = if (segment_id + 1) * frame_rate * segment_duration - 1 < stream_ts.len() {
+            stream_ts[(segment_id + 1) * frame_rate * segment_duration - 1]
+        } else {
+            stream_ts[stream_ts.len() - 1]
+        };
+
+        ranges.push((range_start, range_end));
+    }
+
+    stream_text += "#EXT-X-ENDLIST\n";
+    let _stream_path = format!("{namespace}/stream.m3u8");
+
+    (namespace, playlist_text, stream_text, ranges)
+}
+
\ No newline at end of file diff --git a/src/vidformer/filter.rs.html b/src/vidformer/filter.rs.html new file mode 100644 index 0000000..bb2c3c7 --- /dev/null +++ b/src/vidformer/filter.rs.html @@ -0,0 +1,681 @@ +filter.rs - source

vidformer/
filter.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
//! Filters create and transform video frames
+//!
+//! A filter is a function that takes some inputs and returns a video frame.
+//! For example a filter could blur an input: `MyBlur(frame, amount=5)`.
+
+use crate::dve::AVFrame;
+use opencv::prelude::MatTraitConst;
+use rusty_ffmpeg::ffi;
+use serde::ser::SerializeMap;
+use serde::Deserialize;
+use std::collections::BTreeMap;
+use std::sync::Arc;
+
+pub mod builtin;
+pub mod cv2;
+mod filter_utils;
+
+/// A decoded video frame
+#[derive(Clone)]
+pub struct Frame {
+    inner: Arc<AVFrame>,
+    pub width: i32,
+    pub height: i32,
+    pub format: ffi::AVPixelFormat,
+}
+
+impl serde::Serialize for Frame {
+    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+        let mut map = serializer.serialize_map(Some(4))?;
+        map.serialize_entry("width", &self.width)?;
+        map.serialize_entry("height", &self.height)?;
+
+        let pix_format_name = crate::util::pixel_fmt_str(self.format);
+        map.serialize_entry("format", pix_format_name)?;
+
+        let av_frame: ffi::AVFrame = unsafe { *self.inner.inner };
+        let frame_encoded_size_all_planes =
+            unsafe { ffi::av_image_get_buffer_size(self.format, self.width, self.height, 1) };
+
+        let frame_buffer = vec![0u8; frame_encoded_size_all_planes as usize];
+        let frame_buffer_ptr = frame_buffer.as_ptr() as *mut u8;
+
+        // Copy the frame data to the buffer
+        unsafe {
+            ffi::av_image_copy_to_buffer(
+                frame_buffer_ptr,
+                frame_encoded_size_all_planes,
+                av_frame.data.as_ptr() as *const *const u8,
+                av_frame.linesize.as_ptr(),
+                self.format,
+                self.width,
+                self.height,
+                1,
+            );
+        }
+
+        let frame_buffer = serde_bytes::Bytes::new(&frame_buffer);
+        map.serialize_entry("data", &frame_buffer)?;
+        map.end()
+    }
+}
+
+impl<'de> Deserialize<'de> for Frame {
+    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+        struct FrameVisitor;
+
+        impl<'de> serde::de::Visitor<'de> for FrameVisitor {
+            type Value = Frame;
+
+            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
+                formatter.write_str("a frame")
+            }
+
+            fn visit_map<A: serde::de::MapAccess<'de>>(
+                self,
+                mut map: A,
+            ) -> Result<Self::Value, A::Error> {
+                let mut width = None;
+                let mut height = None;
+                let mut format = None;
+                let mut data = None;
+
+                while let Some(key) = map.next_key()? {
+                    match key {
+                        "width" => {
+                            if width.is_some() {
+                                return Err(serde::de::Error::duplicate_field("width"));
+                            }
+                            width = Some(map.next_value()?);
+                        }
+                        "height" => {
+                            if height.is_some() {
+                                return Err(serde::de::Error::duplicate_field("height"));
+                            }
+                            height = Some(map.next_value()?);
+                        }
+                        "format" => {
+                            if format.is_some() {
+                                return Err(serde::de::Error::duplicate_field("format"));
+                            }
+                            format = Some(map.next_value()?);
+                        }
+                        "data" => {
+                            if data.is_some() {
+                                return Err(serde::de::Error::duplicate_field("data"));
+                            }
+                            data = Some(map.next_value()?);
+                        }
+                        _ => {
+                            return Err(serde::de::Error::unknown_field(
+                                key,
+                                &["width", "height", "format", "data"],
+                            ));
+                        }
+                    }
+                }
+
+                let width: i32 = width.ok_or_else(|| serde::de::Error::missing_field("width"))?;
+                let height: i32 =
+                    height.ok_or_else(|| serde::de::Error::missing_field("height"))?;
+                let format_str: &str =
+                    format.ok_or_else(|| serde::de::Error::missing_field("format"))?;
+
+                let fmt_cstr = std::ffi::CString::new(format_str).unwrap();
+
+                let format = unsafe { ffi::av_get_pix_fmt(fmt_cstr.as_ptr()) };
+                if format == ffi::AVPixelFormat_AV_PIX_FMT_NONE {
+                    return Err(serde::de::Error::custom(format!(
+                        "Invalid pixel format {:?}",
+                        format_str
+                    )));
+                }
+
+                let data: serde_bytes::ByteBuf =
+                    data.ok_or_else(|| serde::de::Error::missing_field("data"))?;
+                let data = data.into_vec();
+
+                // Check we got the right amount of data
+                let frame_encoded_size_all_planes = unsafe {
+                    ffi::av_image_get_buffer_size(format as ffi::AVPixelFormat, width, height, 1)
+                };
+                if data.len() != frame_encoded_size_all_planes as usize {
+                    return Err(serde::de::Error::custom(format!(
+                        "IPC frame data length ({}) does not match expected size ({})",
+                        data.len(),
+                        frame_encoded_size_all_planes
+                    )));
+                }
+
+                if data.len() != frame_encoded_size_all_planes as usize {
+                    return Err(serde::de::Error::custom(
+                        "Data length does not match frame size",
+                    ));
+                }
+
+                let av_frame = unsafe { ffi::av_frame_alloc() };
+                if av_frame.is_null() {
+                    return Err(serde::de::Error::custom("Failed to allocate frame"));
+                }
+
+                unsafe {
+                    (*av_frame).width = width;
+                    (*av_frame).height = height;
+                    (*av_frame).format = format;
+                };
+
+                // alloc frame buffer
+                let ret = unsafe { ffi::av_frame_get_buffer(av_frame, 0) };
+                if ret < 0 {
+                    return Err(serde::de::Error::custom("Failed to allocate frame buffer"));
+                }
+
+                // Copy the data to the frame
+                let num_planes =
+                    unsafe { ffi::av_pix_fmt_count_planes(format as ffi::AVPixelFormat) };
+                if num_planes < 0 {
+                    return Err(serde::de::Error::custom("Failed to get number of planes"));
+                }
+
+                let mut data_offset = 0;
+                for plane in 0..num_planes {
+                    let plane_size = unsafe { (*av_frame).linesize[plane as usize] * height };
+                    unsafe {
+                        std::ptr::copy_nonoverlapping(
+                            // TODO: check linesize[0]
+                            data.as_ptr().add(data_offset),
+                            (*av_frame).data[plane as usize],
+                            plane_size as usize,
+                        );
+                    }
+                    data_offset += plane_size as usize;
+                }
+
+                let frame = AVFrame { inner: av_frame };
+
+                Ok(Frame::new(frame))
+            }
+        }
+
+        deserializer.deserialize_map(FrameVisitor)
+    }
+}
+
+impl Frame {
+    pub(crate) fn new(inner: AVFrame) -> Self {
+        let width = unsafe { (*inner.inner).width };
+        let height = unsafe { (*inner.inner).height };
+        let format = unsafe { (*inner.inner).format };
+        Frame {
+            inner: Arc::new(inner),
+            width,
+            height,
+            format,
+        }
+    }
+
+    pub(crate) fn new_arc(inner: Arc<AVFrame>) -> Self {
+        let width = unsafe { (*inner.inner).width };
+        let height = unsafe { (*inner.inner).height };
+        let format = unsafe { (*inner.inner).format };
+        Frame {
+            inner,
+            width,
+            height,
+            format,
+        }
+    }
+
+    pub(crate) fn inner(&self) -> *mut ffi::AVFrame {
+        self.inner.inner
+    }
+
+    pub(crate) fn into_avframe(self) -> Arc<AVFrame> {
+        self.inner
+    }
+}
+
+impl std::fmt::Debug for Frame {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("Frame")
+            .field("width", &self.width)
+            .field("height", &self.height)
+            .field("format", &self.format)
+            .finish()
+    }
+}
+
+/// A value that can be passed to a filter
+///
+/// This can be a either a video frame or a conventional data value
+#[derive(Debug, Clone, serde::Serialize)]
+pub enum Val {
+    Frame(Frame),
+    FrameType(FrameType),
+    Bool(bool),
+    Int(i64),
+    String(String),
+    Bytes(Vec<u8>),
+    Float(f64),
+    List(Vec<Val>),
+}
+
+#[derive(PartialEq, Eq, Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct FrameType {
+    pub width: usize,
+    pub height: usize,
+    pub format: ffi::AVPixelFormat,
+}
+
+impl FrameType {
+    pub fn new(width: usize, height: usize, format: ffi::AVPixelFormat) -> Self {
+        FrameType {
+            width,
+            height,
+            format,
+        }
+    }
+}
+
+impl Val {
+    pub fn from_expr(expr: &crate::sir::DataExpr, context: &crate::dve::Context) -> Self {
+        match expr {
+            crate::sir::DataExpr::Bool(b) => Val::Bool(*b),
+            crate::sir::DataExpr::Int(i) => Val::Int(*i),
+            crate::sir::DataExpr::String(s) => Val::String(s.to_string()),
+            crate::sir::DataExpr::Bytes(b) => Val::Bytes(b.clone()),
+            crate::sir::DataExpr::Float(f) => Val::Float(*f),
+            crate::sir::DataExpr::ArrayRef(name, crate::sir::IndexConst::ILoc(idx)) => {
+                let array = &context.arrays[name];
+                let val = array.index(*idx);
+                Val::from_expr(&val, context)
+            }
+            crate::sir::DataExpr::ArrayRef(name, crate::sir::IndexConst::T(t)) => {
+                let array = &context.arrays[name];
+                let val = array.index_t(*t);
+                Val::from_expr(&val, context)
+            }
+            crate::sir::DataExpr::List(list) => {
+                let list = list
+                    .iter()
+                    .map(|expr| Val::from_expr(expr, context))
+                    .collect();
+                Val::List(list)
+            }
+        }
+    }
+
+    pub(crate) fn as_int(&self) -> Option<i64> {
+        match self {
+            Val::Int(i) => Some(*i),
+            _ => None,
+        }
+    }
+
+    pub(crate) fn as_frame_type(&self) -> Option<&FrameType> {
+        match self {
+            Val::FrameType(frame_type) => Some(frame_type),
+            _ => None,
+        }
+    }
+}
+
+/// A filter that can create a video frame from some inputs
+pub trait Filter: Send + Sync {
+    /// Creates a video frame from some inputs
+    ///
+    /// The inputs are arbitrary and user provided. An input can either be
+    /// ordered (arg) or named (kwargs). This is similar to Python function calls.
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error>;
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, crate::dve::Error>;
+}
+
\ No newline at end of file diff --git a/src/vidformer/filter/builtin.rs.html b/src/vidformer/filter/builtin.rs.html new file mode 100644 index 0000000..ea0e546 --- /dev/null +++ b/src/vidformer/filter/builtin.rs.html @@ -0,0 +1,3939 @@ +builtin.rs - source

vidformer/filter/
builtin.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
+967
+968
+969
+970
+971
+972
+973
+974
+975
+976
+977
+978
+979
+980
+981
+982
+983
+984
+985
+986
+987
+988
+989
+990
+991
+992
+993
+994
+995
+996
+997
+998
+999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
+1879
+1880
+1881
+1882
+1883
+1884
+1885
+1886
+1887
+1888
+1889
+1890
+1891
+1892
+1893
+1894
+1895
+1896
+1897
+1898
+1899
+1900
+1901
+1902
+1903
+1904
+1905
+1906
+1907
+1908
+1909
+1910
+1911
+1912
+1913
+1914
+1915
+1916
+1917
+1918
+1919
+1920
+1921
+1922
+1923
+1924
+1925
+1926
+1927
+1928
+1929
+1930
+1931
+1932
+1933
+1934
+1935
+1936
+1937
+1938
+1939
+1940
+1941
+1942
+1943
+1944
+1945
+1946
+1947
+1948
+1949
+1950
+1951
+1952
+1953
+1954
+1955
+1956
+1957
+1958
+1959
+1960
+1961
+1962
+1963
+1964
+1965
+1966
+1967
+1968
+1969
//! vidformer built-in filters
+
+use crate::dve::AVFrame;
+use crate::dve::Error;
+use crate::filter::*;
+use opencv::core::*;
+use opencv::imgproc;
+use rusty_ffmpeg::ffi;
+use std::collections::BTreeMap;
+use std::ffi::CString;
+use std::ptr;
+use std::sync::Arc;
+
+mod drawutils;
+mod ipc;
+pub use ipc::IPC;
+
+/// vidformer built-in filters
+pub fn filters() -> BTreeMap<String, std::boxed::Box<dyn Filter>> {
+    let mut filters: BTreeMap<String, std::boxed::Box<dyn Filter>> = BTreeMap::new();
+    filters.insert(
+        "PlaceholderFrame".to_string(),
+        std::boxed::Box::new(PlaceholderFrame {}),
+    );
+    filters.insert("Annotate".to_string(), std::boxed::Box::new(Annotate {}));
+    filters.insert("Box".to_string(), std::boxed::Box::new(Box {}));
+    filters.insert(
+        "BoundingBox".to_string(),
+        std::boxed::Box::new(BoundingBox {}),
+    );
+    filters.insert("DrawBox".to_string(), std::boxed::Box::new(DrawBox {}));
+    filters.insert("Scale".to_string(), std::boxed::Box::new(Scale {}));
+    filters.insert(
+        "_inline_mat".to_string(),
+        std::boxed::Box::new(InlineMat {}),
+    );
+    filters.insert("_slice_mat".to_string(), std::boxed::Box::new(SliceMat {}));
+    filters.insert(
+        "_slice_write_mat".to_string(),
+        std::boxed::Box::new(SliceWriteMat {}),
+    );
+    filters.insert("Pad".to_string(), std::boxed::Box::new(Pad {}));
+    filters.insert("HStack".to_string(), std::boxed::Box::new(HStack {}));
+    filters.insert("VStack".to_string(), std::boxed::Box::new(VStack {}));
+    filters.insert("DrawText".to_string(), std::boxed::Box::new(DrawText {}));
+
+    filters
+}
+
+fn avfilter_backed_uniframe(
+    frame: &Arc<AVFrame>,
+    filter: &str,
+) -> Result<Frame, crate::dve::Error> {
+    let buffer_str = CString::new("buffer").unwrap();
+    let buffersink_str = CString::new("buffersink").unwrap();
+
+    let buffersrc = unsafe { rusty_ffmpeg::ffi::avfilter_get_by_name(buffer_str.as_ptr()) };
+    let buffersink = unsafe { rusty_ffmpeg::ffi::avfilter_get_by_name(buffersink_str.as_ptr()) };
+    let mut outputs = unsafe { rusty_ffmpeg::ffi::avfilter_inout_alloc() };
+    if outputs.is_null() {
+        panic!("ERROR could not allocate output");
+    }
+    let mut inputs = unsafe { rusty_ffmpeg::ffi::avfilter_inout_alloc() };
+    if inputs.is_null() {
+        panic!("ERROR could not allocate input");
+    }
+
+    let args: CString = CString::new(format!(
+        "video_size={}x{}:pix_fmt={}:time_base={}/{}:pixel_aspect={}/{}",
+        unsafe { (*frame.inner).width },
+        unsafe { (*frame.inner).height },
+        unsafe { (*frame.inner).format },
+        1, // time base doesn't matter since we're doing single-frame filters only
+        12288,
+        unsafe { (*frame.inner).sample_aspect_ratio.num },
+        unsafe { (*frame.inner).sample_aspect_ratio.den }
+    ))
+    .unwrap();
+
+    let mut filter_graph = unsafe { rusty_ffmpeg::ffi::avfilter_graph_alloc() };
+    if filter_graph.is_null() {
+        panic!("ERROR could not allocate filter graph");
+    }
+    unsafe {
+        (*filter_graph).nb_threads = 1;
+    }
+
+    let mut buffersrc_ctx: *mut ffi::AVFilterContext = ptr::null_mut();
+
+    let in_str = CString::new("in").unwrap();
+    if unsafe {
+        ffi::avfilter_graph_create_filter(
+            &mut buffersrc_ctx,
+            buffersrc,
+            in_str.as_ptr(),
+            args.as_ptr(),
+            std::ptr::null_mut(),
+            filter_graph,
+        )
+    } < 0
+    {
+        panic!("ERROR could not create buffer source");
+    }
+
+    let mut buffersink_ctx: *mut ffi::AVFilterContext = ptr::null_mut();
+    let out_str = CString::new("out").unwrap();
+    if unsafe {
+        ffi::avfilter_graph_create_filter(
+            &mut buffersink_ctx,
+            buffersink,
+            out_str.as_ptr(),
+            std::ptr::null(),
+            std::ptr::null_mut(),
+            filter_graph,
+        )
+    } < 0
+    {
+        panic!("ERROR could not create buffer sink");
+    }
+
+    unsafe {
+        (*outputs).name = CString::new("in").unwrap().into_raw();
+        (*outputs).filter_ctx = buffersrc_ctx;
+        (*outputs).pad_idx = 0;
+        (*outputs).next = std::ptr::null_mut();
+
+        (*inputs).name = CString::new("out").unwrap().into_raw();
+        (*inputs).filter_ctx = buffersink_ctx;
+        (*inputs).pad_idx = 0;
+        (*inputs).next = std::ptr::null_mut();
+    }
+
+    let filter_cstr = CString::new(filter).unwrap();
+    if unsafe {
+        ffi::avfilter_graph_parse_ptr(
+            filter_graph,
+            filter_cstr.as_ptr(),
+            &mut inputs,
+            &mut outputs,
+            std::ptr::null_mut(),
+        )
+    } < 0
+    {
+        panic!("ERROR could not parse filter graph");
+    }
+
+    if unsafe { ffi::avfilter_graph_config(filter_graph, std::ptr::null_mut()) } < 0 {
+        panic!("ERROR could not configure filter graph");
+    }
+
+    // clone frame just in case something mutates it
+    let mut f = unsafe { ffi::av_frame_alloc() };
+    if f.is_null() {
+        panic!("ERROR could not allocate frame");
+    }
+
+    unsafe {
+        (*f).width = (*frame.inner).width;
+        (*f).height = (*frame.inner).height;
+        (*f).format = ffi::AVPixelFormat_AV_PIX_FMT_YUV420P;
+
+        if ffi::av_frame_get_buffer(f, 0) < 0 {
+            panic!(
+                "ERROR could not allocate frame data buffer ({}x{}, {})",
+                (*f).width,
+                (*f).height,
+                (*f).format
+            );
+        }
+    }
+    if unsafe { ffi::av_frame_copy(f, frame.inner) } < 0 {
+        panic!("ERROR could not copy frame data");
+    }
+
+    if unsafe { ffi::av_buffersrc_add_frame_flags(buffersrc_ctx, f, 0) } < 0 {
+        panic!("ERROR could not add frame to buffer source");
+    }
+
+    let filtered_frame = unsafe { ffi::av_frame_alloc() };
+    if filtered_frame.is_null() {
+        panic!("ERROR could not allocate filtered frame");
+    }
+    if unsafe { ffi::av_buffersink_get_frame(buffersink_ctx, filtered_frame) } < 0 {
+        panic!("ERROR could not get frame from buffer sink");
+    }
+
+    let filtered_frame = AVFrame {
+        inner: filtered_frame,
+    };
+
+    unsafe {
+        ffi::av_frame_free(&mut f);
+        ffi::avfilter_inout_free(&mut inputs);
+        ffi::avfilter_inout_free(&mut outputs);
+        ffi::avfilter_graph_free(&mut filter_graph);
+    }
+
+    Ok(Frame::new(filtered_frame))
+}
+
+fn opencv_backed_uniframe<F>(input_frame: &Frame, filter: F) -> Result<Frame, crate::dve::Error>
+where
+    F: FnOnce(&mut Mat),
+{
+    let width = input_frame.width;
+    let height = input_frame.height;
+
+    let data_y = unsafe {
+        std::slice::from_raw_parts(
+            (*input_frame.inner.inner).data[0],
+            (*input_frame.inner.inner).linesize[0] as usize * height as usize,
+        )
+    };
+
+    let data_u = unsafe {
+        std::slice::from_raw_parts(
+            (*input_frame.inner.inner).data[1],
+            (*input_frame.inner.inner).linesize[1] as usize * height as usize / 2,
+        )
+    };
+
+    let data_v = unsafe {
+        std::slice::from_raw_parts(
+            (*input_frame.inner.inner).data[2],
+            (*input_frame.inner.inner).linesize[2] as usize * height as usize / 2,
+        )
+    };
+
+    let mut yuv_data = vec![
+        0;
+        height as usize * width as usize
+            + 2 * (height as usize / 2) * (width as usize / 2)
+    ];
+    yuv_data[..(height as usize * width as usize)].copy_from_slice(data_y);
+    yuv_data[(height as usize * width as usize)
+        ..(height as usize * width as usize + (height as usize / 2) * (width as usize / 2))]
+        .copy_from_slice(data_u);
+    yuv_data[(height as usize * width as usize + (height as usize / 2) * (width as usize / 2))..]
+        .copy_from_slice(data_v);
+
+    let mut yuv_mat =
+        Mat::new_rows_cols_with_data_mut(height + height / 2, width, &mut yuv_data).unwrap();
+    let mut bgr_mat = unsafe { Mat::new_size(Size::new(width, height), CV_8UC3).unwrap() };
+    imgproc::cvt_color(&yuv_mat, &mut bgr_mat, imgproc::COLOR_YUV2BGR_I420, 0).unwrap();
+
+    // draw bounding boxes
+
+    filter(&mut bgr_mat);
+
+    // convert back to yuv
+    imgproc::cvt_color(&bgr_mat, &mut yuv_mat, imgproc::COLOR_BGR2YUV_I420, 0).unwrap();
+
+    let f = unsafe { ffi::av_frame_alloc() };
+    unsafe {
+        (*f).width = width;
+        (*f).height = height;
+        (*f).format = ffi::AVPixelFormat_AV_PIX_FMT_YUV420P;
+
+        if ffi::av_frame_get_buffer(f, 0) < 0 {
+            panic!("ERROR could not allocate frame data");
+        }
+    }
+
+    // copy data
+    let data_y = unsafe {
+        std::slice::from_raw_parts_mut((*f).data[0], (*f).linesize[0] as usize * height as usize)
+    };
+    let data_u = unsafe {
+        std::slice::from_raw_parts_mut(
+            (*f).data[1],
+            (*f).linesize[1] as usize * height as usize / 2,
+        )
+    };
+    let data_v = unsafe {
+        std::slice::from_raw_parts_mut(
+            (*f).data[2],
+            (*f).linesize[2] as usize * height as usize / 2,
+        )
+    };
+
+    data_y.copy_from_slice(&yuv_data[..(height as usize * width as usize)]);
+    data_u.copy_from_slice(
+        &yuv_data[(height as usize * width as usize)
+            ..(height as usize * width as usize + (height as usize / 2) * (width as usize / 2))],
+    );
+    data_v.copy_from_slice(
+        &yuv_data
+            [(height as usize * width as usize + (height as usize / 2) * (width as usize / 2))..],
+    );
+
+    Ok(Frame::new(AVFrame { inner: f }))
+}
+
+pub struct PlaceholderFrame {}
+impl super::Filter for PlaceholderFrame {
+    fn filter(
+        &self,
+        _args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        let width = kwargs.get("width").unwrap().as_int().unwrap();
+        let height: i64 = kwargs.get("height").unwrap().as_int().unwrap();
+
+        let f = unsafe { ffi::av_frame_alloc() };
+        unsafe {
+            (*f).width = width as i32;
+            (*f).height = height as i32;
+            (*f).format = ffi::AVPixelFormat_AV_PIX_FMT_YUV420P;
+
+            if ffi::av_frame_get_buffer(f, 0) < 0 {
+                panic!("ERROR could not allocate frame data");
+            }
+        }
+
+        for y in 0..unsafe { (*f).height } as usize {
+            for x in 0..unsafe { (*f).width } as usize {
+                unsafe {
+                    *(*f).data[0].add(y * (*f).linesize[0] as usize + x) = ((x + y) % 256) as u8;
+                }
+            }
+        }
+
+        for y in 0..unsafe { (*f).height } as usize / 2 {
+            for x in 0..unsafe { (*f).width } as usize / 2 {
+                unsafe {
+                    *(*f).data[1].add(y * (*f).linesize[1] as usize + x) = ((x + y) % 256) as u8;
+                    *(*f).data[2].add(y * (*f).linesize[2] as usize + x) = ((x + y) % 256) as u8;
+                }
+            }
+        }
+
+        Ok(Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        _args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        let width = kwargs.get("width").unwrap().as_int().unwrap();
+        let height: i64 = kwargs.get("height").unwrap().as_int().unwrap();
+
+        Ok(FrameType::new(
+            width as usize,
+            height as usize,
+            ffi::AVPixelFormat_AV_PIX_FMT_YUV420P,
+        ))
+    }
+}
+
+pub struct Annotate {}
+impl super::Filter for Annotate {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        assert!(args.len() == 1);
+        assert!(kwargs.is_empty());
+
+        let input_frame = match &args[0] {
+            Val::Frame(f) => f,
+            _ => panic!("Expected frame"),
+        };
+
+        assert_eq!(input_frame.format, ffi::AVPixelFormat_AV_PIX_FMT_YUV420P);
+
+        let f = unsafe { ffi::av_frame_alloc() };
+        unsafe {
+            (*f).width = input_frame.width;
+            (*f).height = input_frame.height;
+            (*f).format = ffi::AVPixelFormat_AV_PIX_FMT_YUV420P;
+
+            if ffi::av_frame_get_buffer(f, 0) < 0 {
+                panic!("ERROR could not allocate frame data");
+            }
+        }
+
+        if unsafe { ffi::av_frame_copy(f, input_frame.inner()) } < 0 {
+            panic!("ERROR could not copy frame data");
+        }
+
+        for y in 100..200 {
+            for x in 100..200 {
+                unsafe {
+                    *(*f).data[0].add(y * (*f).linesize[0] as usize + x) = ((x + y) % 256) as u8;
+                }
+            }
+        }
+
+        for y in 100..200 {
+            for x in 100..200 {
+                unsafe {
+                    let x = x / 2;
+                    let y = y / 2;
+
+                    *(*f).data[1].add(y * (*f).linesize[1] as usize + x) = ((x + y) % 256) as u8;
+                    *(*f).data[2].add(y * (*f).linesize[2] as usize + x) = ((x + y) % 256) as u8;
+                }
+            }
+        }
+
+        Ok(Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        _args: &[Val],
+        _kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        todo!()
+    }
+}
+
+pub struct Box {}
+impl super::Filter for Box {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        assert!(args.len() == 1);
+        assert!(kwargs.is_empty());
+
+        let input_frame = match &args[0] {
+            Val::Frame(f) => f,
+            _ => panic!("Expected frame"),
+        };
+
+        avfilter_backed_uniframe(
+            &input_frame.inner,
+            "drawbox=x=100:y=100:w=100:h=100:color=Cyan",
+        )
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        _kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        let input_frame = &args[0];
+        match input_frame {
+            Val::FrameType(frame_type) => Ok(frame_type.clone()),
+            _ => Err(Error::MissingFilterArg),
+        }
+    }
+}
+
+pub struct BoundingBox {}
+
+/*
+   For example: [{"class": "person", "confidence": 0.9243842363357544, "x1": 2049.759765625, "y1": 244.0765838623047, "x2": 3025.21875, "y2": 1714.0}, {"class": "person", "confidence": 0.9086535573005676, "x1": 1062.2205810546875, "y1": 111.629638671875, "x2": 1809.4146728515625, "y2": 1708.45458984375}]
+*/
+#[allow(dead_code)] // used in parsing
+#[derive(Debug, serde::Deserialize)]
+pub struct BoundingBoxBound {
+    class: String,
+    confidence: f64,
+    x1: f64,
+    y1: f64,
+    x2: f64,
+    y2: f64,
+}
+
+impl super::Filter for BoundingBox {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        assert!(args.len() == 1);
+        let bounds_str = match kwargs.get("bounds").unwrap() {
+            Val::String(s) => s,
+            _ => panic!("Expected string"),
+        };
+
+        let bounds: Vec<BoundingBoxBound> = serde_json::from_str(bounds_str).unwrap();
+
+        let input_frame = match &args[0] {
+            Val::Frame(f) => f,
+            _ => panic!("Expected frame"),
+        };
+
+        if bounds.is_empty() {
+            let frame_copy = unsafe { ffi::av_frame_clone(input_frame.inner.inner) };
+            return Ok(Frame::new(AVFrame { inner: frame_copy }));
+        }
+
+        let filter = |frame: &mut Mat| {
+            for bound in bounds {
+                let x1 = bound.x1 as i32;
+                let y1 = bound.y1 as i32;
+                let x2 = bound.x2 as i32;
+                let y2 = bound.y2 as i32;
+
+                let color = Scalar::new(255.0, 0.0, 0.0, 0.0);
+                let thickness = 2;
+                let line_type = opencv::imgproc::LINE_8;
+                let shift = 0;
+
+                let pt1 = Point::new(x1, y1);
+                let pt2 = Point::new(x2, y2);
+
+                opencv::imgproc::rectangle(
+                    frame,
+                    Rect2i::from_points(pt1, pt2),
+                    color,
+                    thickness,
+                    line_type,
+                    shift,
+                )
+                .unwrap();
+            }
+        };
+
+        opencv_backed_uniframe(input_frame, filter)
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        _kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        let frame = args[0].as_frame_type().unwrap();
+        Ok(frame.clone())
+    }
+}
+
+pub struct DrawBox {}
+
+impl super::Filter for DrawBox {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        assert!(args.len() == 1);
+
+        let input_frame = match &args[0] {
+            Val::Frame(f) => f,
+            _ => panic!("Expected frame"),
+        };
+
+        let x1 = match kwargs.get("x1").unwrap() {
+            Val::Int(val) => *val as i32,
+            _ => panic!("Expected a int for x1"),
+        };
+
+        let y1 = match kwargs.get("y1").unwrap() {
+            Val::Int(val) => *val as i32,
+            _ => panic!("Expected a int for y1"),
+        };
+
+        let x2 = match kwargs.get("x2").unwrap() {
+            Val::Int(val) => *val as i32,
+            _ => panic!("Expected a int for x2"),
+        };
+
+        let y2 = match kwargs.get("y2").unwrap() {
+            Val::Int(val) => *val as i32,
+            _ => panic!("Expected a int for y2"),
+        };
+
+        let filter = |frame: &mut Mat| {
+            let color = Scalar::new(255.0, 0.0, 0.0, 0.0);
+            let thickness = 2;
+            let line_type = opencv::imgproc::LINE_8;
+            let shift = 0;
+
+            let pt1 = Point::new(x1, y1);
+            let pt2 = Point::new(x2, y2);
+
+            imgproc::rectangle(
+                frame,
+                opencv::core::Rect2i::from_points(pt1, pt2),
+                color,
+                thickness,
+                line_type,
+                shift,
+            )
+            .unwrap();
+        };
+
+        opencv_backed_uniframe(input_frame, filter)
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        _kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        let frame = args[0].as_frame_type().unwrap();
+        Ok(frame.clone())
+    }
+}
+
+/// Scale & convert pixel format of a frame
+///
+/// # Arguments
+///
+/// * `width` - Width of the output frame (optional, but required if `height` is provided)
+/// * `height` - Height of the output frame (optional, but required if `width` is provided)
+/// * `format` - Pixel format of the output frame (optional)
+pub struct Scale {}
+impl super::Filter for Scale {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        let (width, height) = {
+            if kwargs.contains_key("width") || kwargs.contains_key("height") {
+                if !(kwargs.contains_key("width") && kwargs.contains_key("height")) {
+                    return Err(Error::MissingFilterArg);
+                }
+                (
+                    match kwargs.get("width").unwrap() {
+                        Val::Int(i) => Some(*i as usize),
+                        _ => return Err(Error::MissingFilterArg),
+                    },
+                    match kwargs.get("height").unwrap() {
+                        Val::Int(i) => Some(*i as usize),
+                        _ => return Err(Error::MissingFilterArg),
+                    },
+                )
+            } else {
+                (None, None)
+            }
+        };
+
+        let format = {
+            if kwargs.contains_key("pix_fmt") {
+                match kwargs.get("pix_fmt").unwrap() {
+                    Val::String(s) => {
+                        let format_cstr = CString::new(s.as_str()).unwrap();
+                        let format = unsafe { ffi::av_get_pix_fmt(format_cstr.as_ptr()) };
+                        if format == ffi::AVPixelFormat_AV_PIX_FMT_NONE {
+                            return Err(Error::InvalidFilterArgValue(
+                                s.clone(),
+                                "Invalid pixel format".to_string(),
+                            ));
+                        }
+                        Some(format)
+                    }
+                    _ => return Err(Error::MissingFilterArg),
+                }
+            } else {
+                None
+            }
+        };
+
+        assert!(args.len() == 1);
+
+        let input_frame = match &args[0] {
+            Val::Frame(f) => f,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        let output_type = FrameType {
+            width: width.unwrap_or(input_frame.width as usize),
+            height: height.unwrap_or(input_frame.height as usize),
+            format: format.unwrap_or(input_frame.format),
+        };
+
+        let swscale_ctx = unsafe {
+            ffi::sws_getContext(
+                input_frame.width,
+                input_frame.height,
+                input_frame.format,
+                output_type.width as i32,
+                output_type.height as i32,
+                output_type.format,
+                ffi::SWS_BICUBIC as i32,
+                std::ptr::null_mut(),
+                std::ptr::null_mut(),
+                std::ptr::null_mut(),
+            )
+        };
+
+        let f = unsafe { ffi::av_frame_alloc() };
+        unsafe {
+            (*f).width = output_type.width as i32;
+            (*f).height = output_type.height as i32;
+            (*f).format = output_type.format;
+
+            if ffi::av_frame_get_buffer(f, 0) < 0 {
+                panic!("ERROR could not allocate frame data");
+            }
+        }
+
+        unsafe {
+            ffi::sws_scale(
+                swscale_ctx,
+                (*input_frame.inner.inner).data.as_ptr() as *const *const u8,
+                (*input_frame.inner.inner).linesize.as_ptr(),
+                0,
+                input_frame.height,
+                (*f).data.as_mut_ptr(),
+                (*f).linesize.as_mut_ptr(),
+            );
+        }
+
+        unsafe {
+            ffi::sws_freeContext(swscale_ctx);
+        }
+
+        Ok(Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        let (width, height) = {
+            if kwargs.contains_key("width") || kwargs.contains_key("height") {
+                if !(kwargs.contains_key("width") && kwargs.contains_key("height")) {
+                    return Err(Error::MissingFilterArg);
+                }
+                (
+                    match kwargs.get("width").unwrap() {
+                        Val::Int(i) => Some(*i),
+                        _ => return Err(Error::MissingFilterArg),
+                    },
+                    match kwargs.get("height").unwrap() {
+                        Val::Int(i) => Some(*i),
+                        _ => return Err(Error::MissingFilterArg),
+                    },
+                )
+            } else {
+                (None, None)
+            }
+        };
+
+        let format = {
+            if kwargs.contains_key("pix_fmt") {
+                match kwargs.get("pix_fmt").unwrap() {
+                    Val::String(s) => {
+                        let format_cstr = CString::new(s.as_str()).unwrap();
+                        let format = unsafe { ffi::av_get_pix_fmt(format_cstr.as_ptr()) };
+                        if format == ffi::AVPixelFormat_AV_PIX_FMT_NONE {
+                            return Err(Error::InvalidFilterArgValue(
+                                s.clone(),
+                                "Invalid pixel format".to_string(),
+                            ));
+                        }
+                        Some(format)
+                    }
+                    _ => return Err(Error::MissingFilterArg),
+                }
+            } else {
+                None
+            }
+        };
+
+        assert!(args.len() == 1);
+
+        let frame = &args[0];
+        match frame {
+            Val::FrameType(frame_type) => {
+                let mut new_frame_type = frame_type.clone();
+                if let Some(width) = width {
+                    assert!(width > 0 && width % 2 == 0);
+                    new_frame_type.width = width as usize;
+                }
+                if let Some(height) = height {
+                    assert!(height > 0 && height % 2 == 0);
+                    new_frame_type.height = height as usize;
+                }
+                if let Some(format) = format {
+                    new_frame_type.format = format;
+                }
+                Ok(new_frame_type)
+            }
+            _ => Err(Error::MissingFilterArg),
+        }
+    }
+}
+
+pub struct InlineMat;
+impl super::Filter for InlineMat {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        let width = match kwargs.get("width").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let height = match kwargs.get("height").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let data = match &args[0] {
+            Val::Bytes(b) => b,
+            _ => panic!("Expected bytes"),
+        };
+
+        let f = unsafe { ffi::av_frame_alloc() };
+        if f.is_null() {
+            panic!("ERROR could not allocate frame");
+        }
+
+        unsafe {
+            (*f).width = width as i32;
+            (*f).height = height as i32;
+            (*f).format = ffi::AVPixelFormat_AV_PIX_FMT_RGB24;
+
+            if ffi::av_frame_get_buffer(f, 0) < 0 {
+                panic!("ERROR could not allocate frame data");
+            }
+        }
+
+        // check if ffmpeg wants padding
+        let linesize = unsafe { (*f).linesize[0] as usize };
+        let data_len = data.len();
+        let data_linesize = width as usize * 3;
+
+        if linesize != data_linesize {
+            for i in 0..height as usize {
+                let src = &data[i * data_linesize..(i + 1) * data_linesize];
+                let dst = unsafe { (*f).data[0].add(i * linesize) };
+                unsafe {
+                    std::ptr::copy_nonoverlapping(src.as_ptr(), dst, data_linesize);
+                }
+            }
+        } else {
+            let src = data.as_ptr();
+            let dst = unsafe { (*f).data[0] };
+            unsafe {
+                std::ptr::copy_nonoverlapping(src, dst, data_len);
+            }
+        }
+
+        Ok(Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        let width = match kwargs.get("width") {
+            Some(Val::Int(i)) => *i,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        let height = match kwargs.get("height") {
+            Some(Val::Int(i)) => *i,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        let pix_fmt = match kwargs.get("pix_fmt") {
+            Some(Val::String(s)) => s,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        if pix_fmt != "rgb24" {
+            return Err(Error::InvalidFilterArgValue(
+                pix_fmt.clone(),
+                "Invalid pixel format".to_string(),
+            ));
+        }
+
+        if args.is_empty() {
+            return Err(Error::MissingFilterArg);
+        }
+
+        if args.len() > 1 {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", args.len()),
+                "Invalid number of arguments".to_string(),
+            ));
+        }
+
+        let data: &Vec<u8> = match args[0] {
+            Val::Bytes(ref b) => b,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        // check if data length matches width, height, and pix_fmt
+        if data.len() != width as usize * height as usize * 3 {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", data.len()),
+                "Invalid data length".to_string(),
+            ));
+        }
+
+        Ok(FrameType {
+            width: width as usize,
+            height: height as usize,
+            format: ffi::AVPixelFormat_AV_PIX_FMT_RGB24,
+        })
+    }
+}
+
+// _slice_mat(frame, miny, maxy, minx, maxx)
+pub struct SliceMat {}
+impl super::Filter for SliceMat {
+    fn filter(
+        &self,
+        args: &[Val],
+        _kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        let frame = match &args[0] {
+            Val::Frame(f) => f,
+            _ => panic!("Expected frame"),
+        };
+
+        let miny = args[1].as_int().unwrap();
+        let maxy = args[2].as_int().unwrap();
+        let minx = args[3].as_int().unwrap();
+        let maxx = args[4].as_int().unwrap();
+
+        // create output frame
+        let f = unsafe { ffi::av_frame_alloc() };
+        if f.is_null() {
+            panic!("ERROR could not allocate frame");
+        }
+
+        unsafe {
+            (*f).width = (maxx - minx) as i32;
+            (*f).height = (maxy - miny) as i32;
+            (*f).format = ffi::AVPixelFormat_AV_PIX_FMT_RGB24;
+
+            if ffi::av_frame_get_buffer(f, 0) < 0 {
+                panic!("ERROR could not allocate frame data");
+            }
+        }
+
+        for y in miny..maxy {
+            let src = unsafe {
+                (*frame.inner.inner).data[0]
+                    .add(y as usize * (*frame.inner.inner).linesize[0] as usize + minx as usize * 3)
+            };
+            let dst = unsafe { (*f).data[0].add((y - miny) as usize * (*f).linesize[0] as usize) };
+            unsafe {
+                std::ptr::copy_nonoverlapping(src, dst, ((maxx - minx) * 3) as usize);
+            }
+        }
+
+        Ok(Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        if args.len() < 5 {
+            return Err(Error::MissingFilterArg);
+        } else if args.len() > 5 {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", args.len()),
+                "Invalid number of arguments".to_string(),
+            ));
+        }
+
+        if !kwargs.is_empty() {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", kwargs.len()),
+                "Invalid number of keyword arguments".to_string(),
+            ));
+        }
+
+        let frame = match args[0] {
+            Val::FrameType(ref f) => f,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        if frame.format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", frame.format),
+                "Invalid pixel format".to_string(),
+            ));
+        }
+
+        let miny = match args[1] {
+            Val::Int(i) => i,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        let maxy = match args[2] {
+            Val::Int(i) => i,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        let minx = match args[3] {
+            Val::Int(i) => i,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        let maxx = match args[4] {
+            Val::Int(i) => i,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        if miny < 0
+            || miny > frame.height as i64
+            || maxy < 0
+            || maxy > frame.height as i64
+            || minx < 0
+            || minx > frame.width as i64
+            || maxx < 0
+            || maxx > frame.width as i64
+            || miny >= maxy
+            || minx >= maxx
+        {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", args),
+                "Invalid slice bounds".to_string(),
+            ));
+        }
+
+        Ok(FrameType {
+            width: (maxx - minx) as usize,
+            height: (maxy - miny) as usize,
+            format: frame.format,
+        })
+    }
+}
+
+// _slice_write_mat(f1, f2, miny, maxy, minx, maxx)
+// equiv to python f1[miny:maxy, minx:maxx] = f2
+pub struct SliceWriteMat {}
+impl super::Filter for SliceWriteMat {
+    fn filter(
+        &self,
+        args: &[Val],
+        _kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        let f1 = match &args[0] {
+            Val::Frame(f) => f,
+            _ => panic!("Expected frame"),
+        };
+
+        let f2 = match &args[1] {
+            Val::Frame(f) => f,
+            _ => panic!("Expected frame"),
+        };
+
+        let miny = args[2].as_int().unwrap() as usize;
+        let maxy = args[3].as_int().unwrap() as usize;
+        let minx = args[4].as_int().unwrap() as usize;
+        let maxx = args[5].as_int().unwrap() as usize;
+
+        let f = unsafe { ffi::av_frame_alloc() };
+        if f.is_null() {
+            panic!("ERROR could not allocate frame");
+        }
+
+        unsafe {
+            (*f).width = f1.width;
+            (*f).height = f1.height;
+            (*f).format = ffi::AVPixelFormat_AV_PIX_FMT_RGB24;
+
+            if ffi::av_frame_get_buffer(f, 0) < 0 {
+                panic!("ERROR could not allocate frame data");
+            }
+        }
+
+        for y in 0..f1.height as usize {
+            let src = unsafe {
+                (*f1.inner.inner).data[0].add(y * (*f1.inner.inner).linesize[0] as usize)
+            };
+            let dst = unsafe { (*f).data[0].add(y * (*f).linesize[0] as usize) };
+            unsafe {
+                std::ptr::copy_nonoverlapping(src, dst, f1.width as usize * 3);
+            }
+
+            if y >= miny && y < maxy {
+                let src = unsafe {
+                    (*f2.inner.inner).data[0]
+                        .add((y - miny) * (*f2.inner.inner).linesize[0] as usize)
+                };
+                let dst = unsafe { (*f).data[0].add(y * (*f).linesize[0] as usize) };
+                unsafe {
+                    std::ptr::copy_nonoverlapping(src, dst.add(minx * 3), (maxx - minx) * 3);
+                }
+            }
+        }
+
+        Ok(Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        if args.len() < 6 {
+            return Err(Error::MissingFilterArg);
+        } else if args.len() > 6 {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", args.len()),
+                "Invalid number of arguments".to_string(),
+            ));
+        }
+
+        if !kwargs.is_empty() {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", kwargs.len()),
+                "Invalid number of keyword arguments".to_string(),
+            ));
+        }
+
+        let f1 = match args[0] {
+            Val::FrameType(ref f) => f,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        let f2 = match args[1] {
+            Val::FrameType(ref f) => f,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        if f1.format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", f1.format),
+                "Invalid pixel format".to_string(),
+            ));
+        }
+
+        if f2.format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", f2.format),
+                "Invalid pixel format".to_string(),
+            ));
+        }
+
+        let miny = match args[2] {
+            Val::Int(i) => i,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        let maxy = match args[3] {
+            Val::Int(i) => i,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        let minx = match args[4] {
+            Val::Int(i) => i,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        let maxx = match args[5] {
+            Val::Int(i) => i,
+            _ => return Err(Error::MissingFilterArg),
+        };
+
+        if miny < 0
+            || miny > f1.height as i64
+            || maxy < 0
+            || maxy > f1.height as i64
+            || minx < 0
+            || minx > f1.width as i64
+            || maxx < 0
+            || maxx > f1.width as i64
+            || miny >= maxy
+            || minx >= maxx
+        {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", args),
+                "Invalid slice bounds".to_string(),
+            ));
+        }
+
+        // check if f2 dimensions match slice dimensions
+        if f2.width != (maxx - minx) as usize || f2.height != (maxy - miny) as usize {
+            return Err(Error::InvalidFilterArgValue(
+                format!("{:?}", args),
+                "Frame f2 does not match slice size".to_string(),
+            ));
+        }
+
+        Ok(FrameType {
+            width: f1.width,
+            height: f1.height,
+            format: f1.format,
+        })
+    }
+}
+
+pub struct Pad {}
+impl super::Filter for Pad {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        let width = match kwargs.get("width").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let height = match kwargs.get("height").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let x = match kwargs.get("x").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let y = match kwargs.get("y").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let input_frame = match &args[0] {
+            Val::Frame(f) => f,
+            _ => panic!("Expected frame"),
+        };
+
+        let f = unsafe { ffi::av_frame_alloc() };
+        if f.is_null() {
+            panic!("ERROR could not allocate frame");
+        }
+
+        unsafe {
+            (*f).width = width as i32;
+            (*f).height = height as i32;
+            (*f).format = ffi::AVPixelFormat_AV_PIX_FMT_YUV420P;
+
+            if ffi::av_frame_get_buffer(f, 0) < 0 {
+                panic!("ERROR could not allocate frame data");
+            }
+        }
+
+        let draw_context: *mut drawutils::FFDrawContext = unsafe {
+            ffi::av_calloc(1, std::mem::size_of::<drawutils::FFDrawContext>())
+                as *mut drawutils::FFDrawContext
+        };
+        if draw_context.is_null() {
+            panic!("ERROR could not allocate draw context");
+        }
+        let ret = unsafe { drawutils::ff_draw_init(draw_context, input_frame.format, 0) };
+        if ret < 0 {
+            panic!("ERROR could not initialize draw context");
+        }
+
+        let color: *mut drawutils::FFDrawColor = unsafe {
+            ffi::av_calloc(1, std::mem::size_of::<drawutils::FFDrawColor>())
+                as *mut drawutils::FFDrawColor
+        };
+        if color.is_null() {
+            panic!("ERROR could not allocate color");
+        }
+
+        let mut color_rgba = [0u8; 4];
+        match kwargs.get("color") {
+            Some(Val::String(s)) => {
+                let color_str = CString::new(s.to_string()).unwrap();
+                let ret = unsafe {
+                    ffi::av_parse_color(
+                        color_rgba.as_ptr() as *mut u8,
+                        color_str.as_ptr(),
+                        -1,
+                        std::ptr::null_mut(),
+                    )
+                };
+                if ret < 0 {
+                    return Err(Error::InvalidFilterArgValue(
+                        s.to_string(),
+                        "Invalid color".to_string(),
+                    ));
+                }
+            }
+            _ => {
+                color_rgba[0] = 0;
+                color_rgba[1] = 0;
+                color_rgba[2] = 0;
+                color_rgba[3] = 255;
+            }
+        }
+
+        unsafe { drawutils::ff_draw_color(draw_context, color, color_rgba.as_ptr()) };
+
+        let in_w = input_frame.width as i64;
+        let in_h = input_frame.height as i64;
+
+        // top bar
+        if y != 0 {
+            unsafe {
+                drawutils::ff_fill_rectangle(
+                    draw_context,
+                    color,
+                    &mut (*f).data as *mut *mut u8,
+                    &mut (*f).linesize as *mut i32,
+                    0,
+                    0,
+                    width as i32,
+                    height as i32,
+                )
+            };
+        }
+
+        // bottom bar
+        if height > y + in_h {
+            unsafe {
+                drawutils::ff_fill_rectangle(
+                    draw_context,
+                    color,
+                    &mut (*f).data as *mut *mut u8,
+                    &mut (*f).linesize as *mut i32,
+                    0,
+                    (y + in_h) as i32,
+                    width as i32,
+                    (height - y - in_h) as i32,
+                )
+            };
+        }
+
+        // left border
+        if x != 0 {
+            unsafe {
+                drawutils::ff_fill_rectangle(
+                    draw_context,
+                    color,
+                    &mut (*f).data as *mut *mut u8,
+                    &mut (*f).linesize as *mut i32,
+                    0,
+                    y as i32,
+                    x as i32,
+                    in_h as i32,
+                )
+            };
+        }
+
+        // copy input frame
+        unsafe {
+            drawutils::ff_copy_rectangle2(
+                draw_context,
+                &mut (*f).data as *mut *mut u8,
+                &mut (*f).linesize as *mut i32,
+                &mut (*input_frame.inner.inner).data as *mut *mut u8,
+                &mut (*input_frame.inner.inner).linesize as *mut i32,
+                x as i32,
+                y as i32,
+                0,
+                0,
+                in_w as i32,
+                in_h as i32,
+            )
+        }
+
+        // right border
+        if width > x + in_w {
+            unsafe {
+                drawutils::ff_fill_rectangle(
+                    draw_context,
+                    color,
+                    &mut (*f).data as *mut *mut u8,
+                    &mut (*f).linesize as *mut i32,
+                    (x + in_w) as i32,
+                    y as i32,
+                    (width - x - in_w) as i32,
+                    in_h as i32,
+                )
+            };
+        }
+
+        unsafe {
+            ffi::av_free(color as *mut std::ffi::c_void);
+            ffi::av_free(draw_context as *mut std::ffi::c_void);
+        }
+
+        Ok(Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, crate::dve::Error> {
+        let _x = match kwargs.get("x").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let _y = match kwargs.get("y").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let width = match kwargs.get("width").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let height = match kwargs.get("height").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let input_frame = match &args[0] {
+            Val::FrameType(f) => f,
+            _ => panic!("Expected frame"),
+        };
+
+        let mut color = [0u8; 4];
+        match kwargs.get("color") {
+            Some(Val::String(s)) => {
+                let color_str = CString::new(s.to_string()).unwrap();
+                let ret = unsafe {
+                    ffi::av_parse_color(
+                        color.as_ptr() as *mut u8,
+                        color_str.as_ptr(),
+                        -1,
+                        std::ptr::null_mut(),
+                    )
+                };
+                if ret < 0 {
+                    return Err(Error::InvalidFilterArgValue(
+                        s.to_string(),
+                        "Invalid color".to_string(),
+                    ));
+                }
+            }
+            _ => {
+                color[0] = 0;
+                color[1] = 0;
+                color[2] = 0;
+                color[3] = 255;
+            }
+        }
+
+        let out_frame_type = FrameType {
+            width: width as usize,
+            height: height as usize,
+            format: input_frame.format,
+        };
+
+        Ok(out_frame_type)
+    }
+}
+
+pub struct HStack {}
+impl super::Filter for HStack {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        let width = match kwargs.get("width").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let height = match kwargs.get("height").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let format = match kwargs.get("format").unwrap() {
+            Val::String(s) => {
+                let format_cstr = CString::new(s.as_str()).unwrap();
+                let format = unsafe { ffi::av_get_pix_fmt(format_cstr.as_ptr()) };
+                if format == ffi::AVPixelFormat_AV_PIX_FMT_NONE {
+                    return Err(Error::InvalidFilterArgValue(
+                        s.clone(),
+                        "Invalid pixel format".to_string(),
+                    ));
+                }
+                format
+            }
+            _ => panic!("Expected string"),
+        };
+
+        // create output frame
+        let f = unsafe { ffi::av_frame_alloc() };
+        if f.is_null() {
+            panic!("ERROR could not allocate frame");
+        }
+
+        unsafe {
+            (*f).width = width as i32;
+            (*f).height = height as i32;
+            (*f).format = format;
+
+            if ffi::av_frame_get_buffer(f, 0) < 0 {
+                panic!("ERROR could not allocate frame data");
+            }
+
+            let draw: *mut drawutils::FFDrawContext =
+                ffi::av_calloc(1, std::mem::size_of::<drawutils::FFDrawContext>())
+                    as *mut drawutils::FFDrawContext;
+
+            if draw.is_null() {
+                panic!("ERROR could not allocate draw context");
+            }
+
+            let ret = drawutils::ff_draw_init(draw, format, 0);
+            if ret < 0 {
+                panic!("ERROR could not initialize draw context");
+            }
+
+            let color_rgba = [0u8, 0u8, 0u8, 255u8];
+            let color: *mut drawutils::FFDrawColor =
+                ffi::av_calloc(1, std::mem::size_of::<drawutils::FFDrawColor>())
+                    as *mut drawutils::FFDrawColor;
+            if color.is_null() {
+                panic!("ERROR could not allocate color");
+            }
+
+            drawutils::ff_draw_color(draw, color, color_rgba.as_ptr());
+
+            // fill with black
+            drawutils::ff_fill_rectangle(
+                draw,
+                color,
+                &mut (*f).data as *mut *mut u8,
+                &mut (*f).linesize as *mut i32,
+                0,
+                0,
+                width as i32,
+                height as i32,
+            );
+
+            ffi::av_free(color as *mut std::ffi::c_void);
+            ffi::av_free(draw as *mut std::ffi::c_void);
+        }
+
+        let input_frames: Vec<&Frame> = args
+            .iter()
+            .map(|arg| match arg {
+                Val::Frame(f) => f,
+                _ => panic!("Expected frame"),
+            })
+            .collect();
+
+        let each_frame_width = width / input_frames.len() as i64;
+
+        for (i, frame) in input_frames.iter().enumerate() {
+            let new_height =
+                (frame.height as f64 / frame.width as f64 * each_frame_width as f64).round() as i64;
+
+            let mut temp_frame = unsafe { ffi::av_frame_alloc() };
+            if temp_frame.is_null() {
+                panic!("ERROR could not allocate frame");
+            }
+
+            unsafe {
+                (*temp_frame).width = each_frame_width as i32;
+                (*temp_frame).height = new_height as i32;
+                (*temp_frame).format = format;
+
+                if ffi::av_frame_get_buffer(temp_frame, 0) < 0 {
+                    panic!("ERROR could not allocate frame data");
+                }
+            }
+
+            let sws_ctx = unsafe {
+                ffi::sws_getContext(
+                    frame.width,
+                    frame.height,
+                    frame.format,
+                    each_frame_width as i32,
+                    new_height as i32,
+                    format,
+                    ffi::SWS_BICUBIC as i32,
+                    std::ptr::null_mut(),
+                    std::ptr::null_mut(),
+                    std::ptr::null_mut(),
+                )
+            };
+
+            unsafe {
+                ffi::sws_scale(
+                    sws_ctx,
+                    (*frame.inner.inner).data.as_ptr() as *const *const u8,
+                    (*frame.inner.inner).linesize.as_ptr(),
+                    0,
+                    frame.height,
+                    (*temp_frame).data.as_mut_ptr(),
+                    (*temp_frame).linesize.as_mut_ptr(),
+                );
+            }
+
+            // Try to keep the image vertically centered
+            let dst_y = (height - new_height) / 2;
+
+            let draw: *mut drawutils::FFDrawContext = unsafe {
+                ffi::av_calloc(1, std::mem::size_of::<drawutils::FFDrawContext>())
+                    as *mut drawutils::FFDrawContext
+            };
+            if draw.is_null() {
+                panic!("ERROR could not allocate draw context");
+            }
+            let ret = unsafe { drawutils::ff_draw_init(draw, format, 0) };
+            if ret < 0 {
+                panic!("ERROR could not initialize draw context");
+            }
+
+            // use ff_copy_rectangle2 to copy temp_frame to f
+            unsafe {
+                drawutils::ff_copy_rectangle2(
+                    draw,
+                    &mut (*f).data as *mut *mut u8,
+                    &mut (*f).linesize as *mut i32,
+                    &mut (*temp_frame).data as *mut *mut u8,
+                    &mut (*temp_frame).linesize as *mut i32,
+                    i as i32 * each_frame_width as i32, // i as i32 * each_frame_width as i32
+                    dst_y as i32,                       // dst_y as i32,
+                    0,
+                    0,
+                    each_frame_width as i32,
+                    new_height as i32,
+                )
+            };
+
+            unsafe {
+                ffi::av_frame_free(&mut temp_frame);
+                ffi::sws_freeContext(sws_ctx);
+                ffi::av_free(draw as *mut std::ffi::c_void);
+            }
+        }
+
+        Ok(Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        let width = match kwargs.get("width").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let height = match kwargs.get("height").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let format = match kwargs.get("format").unwrap() {
+            Val::String(s) => {
+                let format_cstr = CString::new(s.as_str()).unwrap();
+                let format = unsafe { ffi::av_get_pix_fmt(format_cstr.as_ptr()) };
+                if format == ffi::AVPixelFormat_AV_PIX_FMT_NONE {
+                    return Err(Error::InvalidFilterArgValue(
+                        s.clone(),
+                        "Invalid pixel format".to_string(),
+                    ));
+                }
+                format
+            }
+            _ => panic!("Expected string"),
+        };
+
+        for input in args {
+            match input {
+                Val::FrameType(_) => {}
+                _ => return Err(Error::MissingFilterArg),
+            }
+        }
+
+        Ok(FrameType {
+            width: width as usize,
+            height: height as usize,
+            format,
+        })
+    }
+}
+
+pub struct VStack {}
+impl super::Filter for VStack {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        let width = match kwargs.get("width").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let height = match kwargs.get("height").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let format = match kwargs.get("format").unwrap() {
+            Val::String(s) => {
+                let format_cstr = CString::new(s.as_str()).unwrap();
+                let format = unsafe { ffi::av_get_pix_fmt(format_cstr.as_ptr()) };
+                if format == ffi::AVPixelFormat_AV_PIX_FMT_NONE {
+                    return Err(Error::InvalidFilterArgValue(
+                        s.clone(),
+                        "Invalid pixel format".to_string(),
+                    ));
+                }
+                format
+            }
+            _ => panic!("Expected string"),
+        };
+
+        // create output frame
+        let f = unsafe { ffi::av_frame_alloc() };
+        if f.is_null() {
+            panic!("ERROR could not allocate frame");
+        }
+
+        unsafe {
+            (*f).width = width as i32;
+            (*f).height = height as i32;
+            (*f).format = format;
+
+            if ffi::av_frame_get_buffer(f, 0) < 0 {
+                panic!("ERROR could not allocate frame data");
+            }
+
+            let draw: *mut drawutils::FFDrawContext =
+                ffi::av_calloc(1, std::mem::size_of::<drawutils::FFDrawContext>())
+                    as *mut drawutils::FFDrawContext;
+
+            if draw.is_null() {
+                panic!("ERROR could not allocate draw context");
+            }
+
+            let ret = drawutils::ff_draw_init(draw, format, 0);
+            if ret < 0 {
+                panic!("ERROR could not initialize draw context");
+            }
+
+            let color_rgba = [0u8, 0u8, 0u8, 255u8];
+            let color: *mut drawutils::FFDrawColor =
+                ffi::av_calloc(1, std::mem::size_of::<drawutils::FFDrawColor>())
+                    as *mut drawutils::FFDrawColor;
+            if color.is_null() {
+                panic!("ERROR could not allocate color");
+            }
+
+            drawutils::ff_draw_color(draw, color, color_rgba.as_ptr());
+
+            // fill with black
+            drawutils::ff_fill_rectangle(
+                draw,
+                color,
+                &mut (*f).data as *mut *mut u8,
+                &mut (*f).linesize as *mut i32,
+                0,
+                0,
+                width as i32,
+                height as i32,
+            );
+
+            ffi::av_free(color as *mut std::ffi::c_void);
+            ffi::av_free(draw as *mut std::ffi::c_void);
+        }
+
+        let input_frames: Vec<&Frame> = args
+            .iter()
+            .map(|arg| match arg {
+                Val::Frame(f) => f,
+                _ => panic!("Expected frame"),
+            })
+            .collect();
+
+        let each_frame_height = height / input_frames.len() as i64;
+
+        for (i, frame) in input_frames.iter().enumerate() {
+            let new_width = (frame.width as f64 / frame.height as f64 * each_frame_height as f64)
+                .round() as i64;
+
+            let mut temp_frame = unsafe { ffi::av_frame_alloc() };
+            if temp_frame.is_null() {
+                panic!("ERROR could not allocate frame");
+            }
+
+            unsafe {
+                (*temp_frame).width = new_width as i32;
+                (*temp_frame).height = each_frame_height as i32;
+                (*temp_frame).format = format;
+
+                if ffi::av_frame_get_buffer(temp_frame, 0) < 0 {
+                    panic!("ERROR could not allocate frame data");
+                }
+            }
+
+            let sws_ctx = unsafe {
+                ffi::sws_getContext(
+                    frame.width,
+                    frame.height,
+                    frame.format,
+                    new_width as i32,
+                    each_frame_height as i32,
+                    format,
+                    ffi::SWS_BICUBIC as i32,
+                    std::ptr::null_mut(),
+                    std::ptr::null_mut(),
+                    std::ptr::null_mut(),
+                )
+            };
+
+            unsafe {
+                ffi::sws_scale(
+                    sws_ctx,
+                    (*frame.inner.inner).data.as_ptr() as *const *const u8,
+                    (*frame.inner.inner).linesize.as_ptr(),
+                    0,
+                    frame.height,
+                    (*temp_frame).data.as_mut_ptr(),
+                    (*temp_frame).linesize.as_mut_ptr(),
+                );
+            }
+
+            // Try to keep the image horizontally centered
+            let dst_x = (width - new_width) / 2;
+
+            let draw: *mut drawutils::FFDrawContext = unsafe {
+                ffi::av_calloc(1, std::mem::size_of::<drawutils::FFDrawContext>())
+                    as *mut drawutils::FFDrawContext
+            };
+            if draw.is_null() {
+                panic!("ERROR could not allocate draw context");
+            }
+            let ret = unsafe { drawutils::ff_draw_init(draw, format, 0) };
+            if ret < 0 {
+                panic!("ERROR could not initialize draw context");
+            }
+
+            // use ff_copy_rectangle2 to copy temp_frame to f
+            unsafe {
+                drawutils::ff_copy_rectangle2(
+                    draw,
+                    &mut (*f).data as *mut *mut u8,
+                    &mut (*f).linesize as *mut i32,
+                    &mut (*temp_frame).data as *mut *mut u8,
+                    &mut (*temp_frame).linesize as *mut i32,
+                    dst_x as i32,
+                    i as i32 * each_frame_height as i32,
+                    0,
+                    0,
+                    new_width as i32,
+                    each_frame_height as i32,
+                )
+            };
+
+            unsafe {
+                ffi::av_frame_free(&mut temp_frame);
+                ffi::sws_freeContext(sws_ctx);
+                ffi::av_free(draw as *mut std::ffi::c_void);
+            }
+        }
+
+        Ok(Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        let width = match kwargs.get("width").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let height = match kwargs.get("height").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let format = match kwargs.get("format").unwrap() {
+            Val::String(s) => {
+                let format_cstr = CString::new(s.as_str()).unwrap();
+                let format = unsafe { ffi::av_get_pix_fmt(format_cstr.as_ptr()) };
+                if format == ffi::AVPixelFormat_AV_PIX_FMT_NONE {
+                    return Err(Error::InvalidFilterArgValue(
+                        s.clone(),
+                        "Invalid pixel format".to_string(),
+                    ));
+                }
+                format
+            }
+            _ => panic!("Expected string"),
+        };
+
+        for input in args {
+            match input {
+                Val::FrameType(_) => {}
+                _ => return Err(Error::MissingFilterArg),
+            }
+        }
+
+        Ok(FrameType {
+            width: width as usize,
+            height: height as usize,
+            format,
+        })
+    }
+}
+pub struct DrawText {}
+impl super::Filter for DrawText {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        assert!(args.len() == 1);
+
+        let input_frame = match &args[0] {
+            Val::Frame(f) => f,
+            _ => panic!("Expected frame"),
+        };
+
+        let text = match kwargs.get("text").unwrap() {
+            Val::String(s) => s,
+            _ => panic!("Expected string"),
+        };
+
+        let x = match kwargs.get("x").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+        let y = match kwargs.get("y").unwrap() {
+            Val::Int(i) => *i,
+            _ => panic!("Expected int"),
+        };
+
+        let size = match kwargs.get("size") {
+            Some(Val::Int(i)) => *i,
+            _ => 20,
+        };
+        let scale = size as f64 / 20.0;
+
+        let filter = |mat: &mut Mat| {
+            let color = opencv::core::Scalar::new(255.0, 255.0, 255.0, 0.0);
+            let font_face = opencv::imgproc::FONT_HERSHEY_SIMPLEX;
+            let font_scale = scale;
+            let thickness = scale as i32 * 2;
+            let line_type = opencv::imgproc::LINE_8;
+            let bottom_left_origin = false;
+
+            opencv::imgproc::put_text(
+                mat,
+                text,
+                Point::new(x as i32, y as i32),
+                font_face,
+                font_scale,
+                color,
+                thickness,
+                line_type,
+                bottom_left_origin,
+            )
+            .unwrap();
+        };
+
+        opencv_backed_uniframe(input_frame, filter)
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        _kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        let input_frame = &args[0];
+        match input_frame {
+            Val::FrameType(frame_type) => Ok(frame_type.clone()),
+            _ => Err(Error::MissingFilterArg),
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/filter/builtin/drawutils.rs.html b/src/vidformer/filter/builtin/drawutils.rs.html new file mode 100644 index 0000000..a711882 --- /dev/null +++ b/src/vidformer/filter/builtin/drawutils.rs.html @@ -0,0 +1,777 @@ +drawutils.rs - source

vidformer/filter/builtin/
drawutils.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
/// This module reimplements the drawutils.c file from FFmpeg.
+/// We need to reimplement this file because it is not exposed in the FFmpeg Rust bindings.
+///
+/// The goal is to allow `ffi::` to be replaced with `drawutils::` and maintain API compatibility.
+/// The implementation is based on the original C code from FFmpeg and bindgen and cleaned up with manual/ChatGPT updates.
+use rusty_ffmpeg::ffi;
+
+const MAX_PLANES: usize = 4;
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub(crate) struct FFDrawContext {
+    pub(crate) desc: *const ffi::AVPixFmtDescriptor,
+    pub(crate) format: ffi::AVPixelFormat,
+    pub(crate) nb_planes: ::std::os::raw::c_uint,
+    pub(crate) pixelstep: [::std::os::raw::c_int; MAX_PLANES],
+    pub(crate) hsub: [u8; MAX_PLANES],
+    pub(crate) vsub: [u8; MAX_PLANES],
+    pub(crate) hsub_max: u8,
+    pub(crate) vsub_max: u8,
+    pub(crate) range: ffi::AVColorRange,
+    pub(crate) flags: ::std::os::raw::c_uint,
+    pub(crate) csp: ffi::AVColorSpace,
+    pub(crate) rgb2yuv: [[f64; 3usize]; 3usize],
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub(crate) struct FFDrawColor {
+    pub(crate) rgba: [u8; 4usize],
+    pub(crate) comp: [FFDrawColor__bindgen_ty_1; 4usize],
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub(crate) union FFDrawColor__bindgen_ty_1 {
+    pub(crate) u32_: [u32; 4usize],
+    pub(crate) u16_: [u16; 8usize],
+    pub(crate) u8_: [u8; 16usize],
+}
+
+pub(crate) unsafe fn ff_draw_init(
+    draw: *mut FFDrawContext,
+    format: ffi::AVPixelFormat,
+    flags: ::std::os::raw::c_uint,
+) -> ::std::os::raw::c_int {
+    ff_draw_init2(
+        draw,
+        format,
+        ffi::AVColorSpace_AVCOL_SPC_UNSPECIFIED,
+        ffi::AVColorRange_AVCOL_RANGE_UNSPECIFIED,
+        flags,
+    )
+}
+
+pub(crate) unsafe fn ff_draw_init2(
+    draw: *mut FFDrawContext,
+    format: ffi::AVPixelFormat,
+    csp: ffi::AVColorSpace,
+    range: ffi::AVColorRange,
+    flags: ::std::os::raw::c_uint,
+) -> ::std::os::raw::c_int {
+    unsafe {
+        let desc = ffi::av_pix_fmt_desc_get(format);
+        if desc.is_null() || (*desc).name.is_null() {
+            return ffi::AVERROR(ffi::EINVAL);
+        }
+        if (*desc).flags & ffi::AV_PIX_FMT_FLAG_BE as u64 != 0 {
+            return ffi::AVERROR(ffi::ENOSYS);
+        }
+        if (*desc).flags
+            & !(ffi::AV_PIX_FMT_FLAG_PLANAR | ffi::AV_PIX_FMT_FLAG_RGB | ffi::AV_PIX_FMT_FLAG_ALPHA)
+                as u64
+            != 0
+        {
+            return ffi::AVERROR(ffi::ENOSYS);
+        }
+
+        let mut csp = csp;
+        if csp == ffi::AVColorSpace_AVCOL_SPC_UNSPECIFIED {
+            csp = if (*desc).flags & ffi::AV_PIX_FMT_FLAG_RGB as u64 != 0 {
+                ffi::AVColorSpace_AVCOL_SPC_RGB
+            } else {
+                ffi::AVColorSpace_AVCOL_SPC_SMPTE170M
+            };
+        }
+
+        let luma = if (*desc).flags & ffi::AV_PIX_FMT_FLAG_RGB as u64 == 0 {
+            ffi::av_csp_luma_coeffs_from_avcsp(csp)
+        } else {
+            std::ptr::null()
+        };
+        if luma.is_null() && (*desc).flags & ffi::AV_PIX_FMT_FLAG_RGB as u64 == 0 {
+            return ffi::AVERROR(ffi::EINVAL);
+        }
+
+        let mut range = range;
+        if range == ffi::AVColorRange_AVCOL_RANGE_UNSPECIFIED {
+            range = match format {
+                ffi::AVPixelFormat_AV_PIX_FMT_YUVJ420P
+                | ffi::AVPixelFormat_AV_PIX_FMT_YUVJ422P
+                | ffi::AVPixelFormat_AV_PIX_FMT_YUVJ444P
+                | ffi::AVPixelFormat_AV_PIX_FMT_YUVJ411P
+                | ffi::AVPixelFormat_AV_PIX_FMT_YUVJ440P
+                | _ if csp == ffi::AVColorSpace_AVCOL_SPC_RGB => ffi::AVColorRange_AVCOL_RANGE_JPEG,
+                _ => ffi::AVColorRange_AVCOL_RANGE_MPEG,
+            };
+        }
+
+        if range != ffi::AVColorRange_AVCOL_RANGE_JPEG
+            && range != ffi::AVColorRange_AVCOL_RANGE_MPEG
+        {
+            return ffi::AVERROR(ffi::EINVAL);
+        }
+
+        let mut nb_planes = 0;
+        let mut pixelstep = [0i32; MAX_PLANES];
+        let mut depthb = 0;
+
+        for i in 0..(*desc).nb_components {
+            let c = &(*desc).comp[i as usize];
+            if c.depth < 8 || c.depth > 16 {
+                return ffi::AVERROR(ffi::ENOSYS);
+            }
+            if c.plane >= MAX_PLANES as i32 {
+                return ffi::AVERROR(ffi::ENOSYS);
+            }
+            if c.shift != 0 && (c.shift + c.depth) & 0x7 != 0 {
+                return ffi::AVERROR(ffi::ENOSYS);
+            }
+
+            let db = (c.depth + 7) / 8;
+            if depthb != 0 && depthb != db {
+                return ffi::AVERROR(ffi::ENOSYS);
+            }
+            depthb = db;
+            if db * (c.offset + 1) as i32 > 16 {
+                return ffi::AVERROR(ffi::ENOSYS);
+            }
+            if c.offset as i32 % db != 0 {
+                return ffi::AVERROR(ffi::ENOSYS);
+            }
+            if pixelstep[c.plane as usize] != 0 && pixelstep[c.plane as usize] != c.step as i32 {
+                return ffi::AVERROR(ffi::ENOSYS);
+            }
+            pixelstep[c.plane as usize] = c.step as i32;
+            if pixelstep[c.plane as usize] >= 8 {
+                return ffi::AVERROR(ffi::ENOSYS);
+            }
+            nb_planes = nb_planes.max((c.plane + 1) as u32);
+        }
+
+        std::ptr::write(
+            draw,
+            FFDrawContext {
+                desc,
+                format,
+                nb_planes,
+                range,
+                csp,
+                flags,
+                pixelstep,
+                hsub: [(*desc).log2_chroma_w; 4],
+                vsub: [(*desc).log2_chroma_h; 4],
+                hsub_max: (*desc).log2_chroma_w,
+                vsub_max: (*desc).log2_chroma_h,
+                rgb2yuv: [[0.0; 3]; 3],
+            },
+        );
+
+        if !luma.is_null() {
+            ff_fill_rgb2yuv_table(luma.as_ref().unwrap(), &mut (*draw).rgb2yuv);
+        }
+
+        0
+    }
+}
+
+fn ff_fill_rgb2yuv_table(coeffs: &ffi::AVLumaCoefficients, rgb2yuv: &mut [[f64; 3usize]; 3usize]) {
+    let cr = ffi::av_q2d(coeffs.cr);
+    let cg = ffi::av_q2d(coeffs.cg);
+    let cb = ffi::av_q2d(coeffs.cb);
+
+    // Inline the ycgco matrix
+    if cr == 0.25 && cg == 0.5 && cb == 0.25 {
+        *rgb2yuv = [[0.25, 0.5, 0.25], [-0.25, 0.5, -0.25], [0.5, 0.0, -0.5]];
+        return;
+    }
+    // Inline the gbr matrix
+    else if cr == 1.0 && cg == 1.0 && cb == 1.0 {
+        *rgb2yuv = [[0.0, 1.0, 0.0], [0.0, -0.5, 0.5], [0.5, -0.5, 0.0]];
+        return;
+    }
+
+    rgb2yuv[0][0] = cr;
+    rgb2yuv[0][1] = cg;
+    rgb2yuv[0][2] = cb;
+
+    let bscale = 0.5 / (cb - 1.0);
+    let rscale = 0.5 / (cr - 1.0);
+
+    rgb2yuv[1][0] = bscale * cr;
+    rgb2yuv[1][1] = bscale * cg;
+    rgb2yuv[1][2] = 0.5;
+
+    rgb2yuv[2][0] = 0.5;
+    rgb2yuv[2][1] = rscale * cg;
+    rgb2yuv[2][2] = rscale * cb;
+}
+
+pub(crate) unsafe fn ff_draw_color(
+    draw: *mut FFDrawContext,
+    color: *mut FFDrawColor,
+    rgba: *const u8,
+) {
+    unsafe {
+        let draw = &*draw;
+        let color = &mut *color;
+        let desc = &*draw.desc;
+
+        let mut yuvad = [0.0; 4];
+        let mut rgbad = [0.0; 4];
+
+        // Copy rgba to color->rgba if they are not the same
+        if rgba != color.rgba.as_ptr() {
+            std::ptr::copy_nonoverlapping(rgba, color.rgba.as_mut_ptr(), 4);
+        }
+
+        // Initialize color->comp to zero
+        std::ptr::write_bytes(color.comp.as_mut_ptr(), 0, color.comp.len());
+
+        // Normalize RGBA values to the [0, 1] range
+        for i in 0..4 {
+            rgbad[i] = color.rgba[i] as f64 / 255.0;
+        }
+
+        // Convert RGB to YUV if necessary
+        if desc.flags & ffi::AV_PIX_FMT_FLAG_RGB as u64 != 0 {
+            yuvad[..3].copy_from_slice(&rgbad[..3]);
+        } else {
+            ff_matrix_mul_3x3_vec(&mut yuvad, &rgbad, &draw.rgb2yuv);
+        }
+
+        // Alpha channel
+        yuvad[3] = rgbad[3];
+
+        // Adjust YUV values according to the color range
+        for i in 0..3 {
+            let chroma = (desc.flags & ffi::AV_PIX_FMT_FLAG_RGB as u64 == 0) && i > 0;
+            if draw.range == ffi::AVColorRange_AVCOL_RANGE_MPEG {
+                yuvad[i] *= if chroma { 224.0 / 255.0 } else { 219.0 / 255.0 };
+                yuvad[i] += if chroma { 128.0 / 255.0 } else { 16.0 / 255.0 };
+            } else if chroma {
+                yuvad[i] += 0.5;
+            }
+        }
+
+        // Handle grayscale formats
+        if desc.nb_components <= 2 {
+            yuvad[1] = yuvad[3];
+        }
+
+        // Pack the YUV values into the color->comp array
+        for i in 0..desc.nb_components as usize {
+            let val = (yuvad[i] * ((1 << (desc.comp[i].depth + desc.comp[i].shift)) - 1) as f64
+                + 0.5)
+                .round() as u32;
+
+            if desc.comp[i].depth > 8 {
+                color.comp[desc.comp[i].plane as usize].u16_[desc.comp[i].offset as usize / 2] =
+                    val as u16;
+            } else {
+                color.comp[desc.comp[i].plane as usize].u8_[desc.comp[i].offset as usize] =
+                    val as u8;
+            }
+        }
+    }
+}
+
+fn ff_matrix_mul_3x3_vec(dst: &mut [f64; 4], src: &[f64; 4], mat: &[[f64; 3usize]; 3usize]) {
+    for i in 0..3 {
+        dst[i] = mat[i][0] * src[0] + mat[i][1] * src[1] + mat[i][2] * src[2];
+    }
+}
+
+fn pointer_at(
+    draw: &FFDrawContext,
+    data: &[*mut u8],
+    linesize: &[::std::os::raw::c_int],
+    plane: usize,
+    x: ::std::os::raw::c_int,
+    y: ::std::os::raw::c_int,
+) -> *mut u8 {
+    unsafe {
+        data[plane].offset(
+            ((y >> draw.vsub[plane]) * linesize[plane]
+                + (x >> draw.hsub[plane]) * draw.pixelstep[plane]) as isize,
+        )
+    }
+}
+
+pub(crate) unsafe fn ff_copy_rectangle2(
+    draw: *mut FFDrawContext,
+    dst: *mut *mut u8,
+    dst_linesize: *mut ::std::os::raw::c_int,
+    src: *mut *mut u8,
+    src_linesize: *mut ::std::os::raw::c_int,
+    dst_x: ::std::os::raw::c_int,
+    dst_y: ::std::os::raw::c_int,
+    src_x: ::std::os::raw::c_int,
+    src_y: ::std::os::raw::c_int,
+    w: ::std::os::raw::c_int,
+    h: ::std::os::raw::c_int,
+) {
+    unsafe {
+        let draw = &*draw;
+        let dst = std::slice::from_raw_parts_mut(dst, draw.nb_planes as usize);
+        let dst_linesize = std::slice::from_raw_parts_mut(dst_linesize, draw.nb_planes as usize);
+        let src = std::slice::from_raw_parts_mut(src, draw.nb_planes as usize);
+        let src_linesize = std::slice::from_raw_parts_mut(src_linesize, draw.nb_planes as usize);
+
+        for plane in 0..draw.nb_planes as usize {
+            let mut p = pointer_at(draw, src, src_linesize, plane, src_x, src_y);
+            let mut q = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
+            let wp =
+                ((w + (1 << draw.hsub[plane]) - 1) >> draw.hsub[plane]) * draw.pixelstep[plane];
+            let hp = (h + (1 << draw.vsub[plane]) - 1) >> draw.vsub[plane];
+
+            for _ in 0..hp {
+                std::ptr::copy_nonoverlapping(p, q, wp as usize);
+                p = p.offset(src_linesize[plane] as isize);
+                q = q.offset(dst_linesize[plane] as isize);
+            }
+        }
+    }
+}
+
+pub(crate) unsafe fn ff_fill_rectangle(
+    draw: *mut FFDrawContext,
+    color: *mut FFDrawColor,
+    dst: *mut *mut u8,
+    dst_linesize: *mut ::std::os::raw::c_int,
+    dst_x: ::std::os::raw::c_int,
+    dst_y: ::std::os::raw::c_int,
+    w: ::std::os::raw::c_int,
+    h: ::std::os::raw::c_int,
+) {
+    unsafe {
+        let draw = &*draw;
+        let color = &mut *color;
+        let dst = std::slice::from_raw_parts_mut(dst, draw.nb_planes as usize);
+        let dst_linesize = std::slice::from_raw_parts_mut(dst_linesize, draw.nb_planes as usize);
+
+        for plane in 0..draw.nb_planes as usize {
+            let p0 = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
+            let wp = ((w + (1 << draw.hsub[plane]) - 1) >> draw.hsub[plane]) as usize;
+            let hp = ((h + (1 << draw.vsub[plane]) - 1) >> draw.vsub[plane]) as usize;
+            if hp == 0 {
+                return;
+            }
+            let mut p = p0;
+
+            // Handle big-endian systems with depth > 8
+            if cfg!(target_endian = "big") && draw.desc.as_ref().unwrap().comp[0].depth > 8 {
+                for x in 0..(draw.pixelstep[plane] / 2) as usize {
+                    color.comp[plane].u16_[x] = color.comp[plane].u16_[x].swap_bytes();
+                }
+            }
+
+            // Copy the first line from color
+            for _ in 0..wp {
+                std::ptr::copy_nonoverlapping(
+                    color.comp[plane].u8_.as_ptr(),
+                    p,
+                    draw.pixelstep[plane] as usize,
+                );
+                p = p.offset(draw.pixelstep[plane] as isize);
+            }
+
+            // Copy the rest of the lines from the first line
+            let wp_bytes = (wp * draw.pixelstep[plane] as usize) as isize;
+            p = p0.offset(dst_linesize[plane] as isize);
+            for _ in 1..hp {
+                std::ptr::copy_nonoverlapping(p0, p, wp_bytes as usize);
+                p = p.offset(dst_linesize[plane] as isize);
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/filter/builtin/ipc.rs.html b/src/vidformer/filter/builtin/ipc.rs.html new file mode 100644 index 0000000..a80ec16 --- /dev/null +++ b/src/vidformer/filter/builtin/ipc.rs.html @@ -0,0 +1,385 @@ +ipc.rs - source

vidformer/filter/builtin/
ipc.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
use crate::dve::Error;
+use crate::filter::*;
+use std::collections::BTreeMap;
+use std::io::Read;
+use std::io::Write;
+
+/// Filter over IPC Socket
+///
+/// This filter sends requests to a filter server over a Unix socket.
+/// TODO: Wire protocol documentation
+pub struct IPC {
+    pub(crate) socket: String,
+    pub(crate) func: String,
+    pub(crate) state: parking_lot::Mutex<IPCFilterState>,
+}
+
+impl IPC {
+    pub fn new(socket: String, func: String) -> Result<Self, Error> {
+        let stream = std::os::unix::net::UnixStream::connect(&socket).map_err(|e| {
+            Error::FilterInternalError(format!(
+                "Failed to connect to IPC socket {}: {:?}",
+                &socket, e
+            ))
+        })?;
+
+        log::info!("Connected to IPC socket {}", &socket);
+        Ok(Self {
+            socket,
+            func,
+            state: parking_lot::Mutex::new(IPCFilterState { stream }),
+        })
+    }
+
+    pub fn via_map(config: &BTreeMap<String, String>) -> Result<Self, Error> {
+        let socket = config
+            .get("socket")
+            .ok_or_else(|| Error::Unknown("Missing 'socket' key".to_string()))?;
+
+        let func = config
+            .get("func")
+            .ok_or_else(|| Error::Unknown("Missing 'func' key".to_string()))?;
+
+        Self::new(socket.clone(), func.clone())
+    }
+}
+
+pub(crate) struct IPCFilterState {
+    pub(crate) stream: std::os::unix::net::UnixStream,
+}
+
+impl IPCFilterState {
+    pub(crate) fn rpc(&mut self, req: &[u8]) -> Result<Vec<u8>, Error> {
+        let req_len: u32 = req
+            .len()
+            .try_into()
+            .map_err(|_| Error::FilterInternalError("IPC request too large".to_string()))?;
+        self.stream.write_all(&req_len.to_be_bytes()).map_err(|e| {
+            Error::FilterInternalError(format!("Failed to write IPC request length: {:?}", e))
+        })?;
+        self.stream.write_all(req).map_err(|e| {
+            Error::FilterInternalError(format!("Failed to write IPC request: {:?}", e))
+        })?;
+        self.stream.flush().map_err(|e| {
+            Error::FilterInternalError(format!("Failed to flush IPC request: {:?}", e))
+        })?;
+
+        let mut response_len_bytes = [0u8; 4];
+        self.stream
+            .read_exact(&mut response_len_bytes)
+            .map_err(|e| {
+                Error::FilterInternalError(format!("Failed to read IPC response length: {:?}", e))
+            })?;
+        let response_len = u32::from_be_bytes(response_len_bytes);
+        let mut response_bytes = vec![0u8; response_len as usize];
+        self.stream.read_exact(&mut response_bytes).map_err(|e| {
+            Error::FilterInternalError(format!("Failed to read IPC response: {:?}", e))
+        })?;
+        Ok(response_bytes)
+    }
+}
+
+#[derive(Debug, serde::Serialize)]
+pub(crate) struct IPCFilterRequest {
+    pub(crate) func: String,
+    pub(crate) op: &'static str,
+    pub(crate) args: Vec<Val>,
+    pub(crate) kwargs: BTreeMap<String, Val>,
+}
+
+#[derive(Debug, serde::Deserialize)]
+pub(crate) struct IPCFilterResponse {
+    pub(crate) frame: Frame,
+}
+
+#[derive(Debug, serde::Serialize)]
+pub(crate) struct IPCFilterTypeRequest {
+    pub(crate) func: String,
+    pub(crate) op: &'static str,
+    pub(crate) args: Vec<Val>,
+    pub(crate) kwargs: BTreeMap<String, Val>,
+}
+
+#[derive(Debug, serde::Deserialize)]
+pub(crate) struct IPCFilterTypeResponse {
+    pub(crate) frame_type: FrameType,
+}
+
+impl crate::filter::Filter for IPC {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, crate::dve::Error> {
+        let request = IPCFilterRequest {
+            func: self.func.clone(),
+            op: "filter",
+            args: args.to_vec(),
+            kwargs: kwargs.clone(),
+        };
+        let req_bytes = rmp_serde::to_vec_named(&request).map_err(|e| {
+            Error::FilterInternalError(format!("Failed to serialize IPC request: {:?}", e))
+        })?;
+
+        let mut state = self.state.lock();
+        let response_bytes = state.rpc(&req_bytes)?;
+        drop(state);
+
+        let response: IPCFilterResponse = rmp_serde::from_slice(&response_bytes).map_err(|e| {
+            Error::FilterInternalError(format!(
+                "Failed to deserialize filter IPC response from {}: {:?}",
+                self.socket, e
+            ))
+        })?;
+
+        Ok(response.frame)
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error> {
+        for (i, arg) in args.iter().enumerate() {
+            if let Val::FrameType(ft) = arg {
+                if ft.format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+                    return Err(Error::FilterInternalError(format!(
+                        "Unsupported pixel format {} in argument {}",
+                        crate::util::pixel_fmt_str(ft.format),
+                        i
+                    )));
+                }
+            }
+        }
+
+        for (key, val) in kwargs.iter() {
+            if let Val::FrameType(ft) = val {
+                if ft.format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+                    return Err(Error::FilterInternalError(format!(
+                        "Unsupported pixel format {:?} in keyword argument {}",
+                        crate::util::pixel_fmt_str(ft.format),
+                        key
+                    )));
+                }
+            }
+        }
+
+        let request = IPCFilterTypeRequest {
+            func: self.func.clone(),
+            op: "filter_type",
+            args: args.to_vec(),
+            kwargs: kwargs.clone(),
+        };
+        let req_bytes = rmp_serde::to_vec_named(&request).map_err(|e| {
+            Error::FilterInternalError(format!("Failed to serialize IPC request: {:?}", e))
+        })?;
+
+        let mut state: parking_lot::lock_api::MutexGuard<parking_lot::RawMutex, IPCFilterState> =
+            self.state.lock();
+        let response_bytes = state.rpc(&req_bytes)?;
+        drop(state);
+
+        let response: IPCFilterTypeResponse =
+            rmp_serde::from_slice(&response_bytes).map_err(|e| {
+                Error::FilterInternalError(format!(
+                    "Failed to deserialize filter_type IPC response from {}: {:?}",
+                    self.socket, e
+                ))
+            })?;
+
+        Ok(response.frame_type)
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/filter/cv2.rs.html b/src/vidformer/filter/cv2.rs.html new file mode 100644 index 0000000..91fed86 --- /dev/null +++ b/src/vidformer/filter/cv2.rs.html @@ -0,0 +1,2199 @@ +cv2.rs - source

vidformer/filter/
cv2.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
+967
+968
+969
+970
+971
+972
+973
+974
+975
+976
+977
+978
+979
+980
+981
+982
+983
+984
+985
+986
+987
+988
+989
+990
+991
+992
+993
+994
+995
+996
+997
+998
+999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
//! vidformer cv2 filters
+
+use crate::dve;
+use crate::dve::AVFrame;
+use crate::filter;
+use crate::filter::Val;
+use crate::filter::*;
+use filter::filter_utils::*;
+use opencv::imgproc;
+use opencv::prelude::MatTrait;
+use rusty_ffmpeg::ffi;
+use std::collections::BTreeMap;
+
+/// vidformer cv2 filters
+pub fn filters() -> BTreeMap<String, Box<dyn filter::Filter>> {
+    let mut filters: BTreeMap<String, Box<dyn filter::Filter>> = BTreeMap::new();
+    filters.insert("cv2.rectangle".to_string(), Box::new(Rectangle {}));
+    filters.insert("cv2.putText".to_string(), Box::new(PutText {}));
+    filters.insert("cv2.arrowedLine".to_string(), Box::new(ArrowedLine {}));
+    filters.insert("cv2.line".to_string(), Box::new(Line {}));
+    filters.insert("cv2.circle".to_string(), Box::new(Circle {}));
+    filters.insert("cv2.setTo".to_string(), Box::new(SetTo {}));
+    filters.insert("cv2.addWeighted".to_string(), Box::new(AddWeighted {}));
+    filters
+}
+
+pub struct Rectangle {}
+
+struct RectangleArgs {
+    img: filter_utils::FrameArg,
+    pt1: (i32, i32),
+    pt2: (i32, i32),
+    color: [f64; 4],
+    thickness: i32,
+    linetype: i32,
+    shift: i32,
+}
+
+impl Rectangle {
+    fn args(
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> Result<RectangleArgs, String> {
+        let signature = filter_utils::FunctionSignature {
+            parameters: vec![
+                Parameter::Positional { name: "img" },
+                Parameter::Positional { name: "pt1" },
+                Parameter::Positional { name: "pt2" },
+                Parameter::Positional { name: "color" },
+                Parameter::PositionalOptional {
+                    name: "thickness",
+                    default_value: Val::Int(1),
+                },
+                Parameter::PositionalOptional {
+                    name: "lineType",
+                    default_value: Val::Int(8),
+                },
+                Parameter::PositionalOptional {
+                    name: "shift",
+                    default_value: Val::Int(0),
+                },
+            ],
+        };
+
+        let kwargs = kwargs.clone();
+        let args = args.to_vec();
+        let parsed_args = filter_utils::parse_arguments(&signature, args, kwargs)?;
+
+        let img = match parsed_args.get("img") {
+            Some(Val::Frame(frame)) => filter_utils::FrameArg::Frame(frame.clone()),
+            Some(Val::FrameType(frame_type)) => {
+                filter_utils::FrameArg::FrameType(frame_type.clone())
+            }
+            x => {
+                dbg! {x};
+                return Err("Expected 'img' to be a Frame".into());
+            }
+        };
+
+        // pt1 is a list of two integers
+        let pt1 = filter_utils::get_point(&parsed_args, "pt1")?;
+
+        // pt2 is a list of two integers
+        let pt2 = filter_utils::get_point(&parsed_args, "pt2")?;
+
+        // color is a list of four floats
+        let color = filter_utils::get_color(&parsed_args)?;
+
+        // thickness is an integer
+        let thickness = match parsed_args.get("thickness") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'thickness' to be an integer".into()),
+        };
+
+        // lineType is an integer
+        let linetype = match parsed_args.get("lineType") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'lineType' to be an integer".into()),
+        };
+
+        // shift is an integer
+        let shift = match parsed_args.get("shift") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'shift' to be an integer".into()),
+        };
+
+        Ok(RectangleArgs {
+            img,
+            pt1,
+            pt2,
+            color,
+            thickness,
+            linetype,
+            shift,
+        })
+    }
+}
+
+impl filter::Filter for Rectangle {
+    fn filter(
+        &self,
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> std::result::Result<filter::Frame, dve::Error> {
+        let opts: RectangleArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(dve::Error::AVError(err)),
+        };
+
+        let img = opts.img.unwrap_frame();
+        let (width, height) = (img.width, img.height);
+        debug_assert_eq!(img.format, ffi::AVPixelFormat_AV_PIX_FMT_RGB24);
+
+        let mut mat = filter_utils::frame_to_mat_rgb24(&img, width, height);
+
+        let pt1 = opencv::core::Point::new(opts.pt1.0, opts.pt1.1);
+        let pt2 = opencv::core::Point::new(opts.pt2.0, opts.pt2.1);
+
+        let color =
+            opencv::core::Scalar::new(opts.color[0], opts.color[1], opts.color[2], opts.color[3]);
+
+        imgproc::rectangle_points(
+            &mut mat,
+            pt1,
+            pt2,
+            color,
+            opts.thickness,
+            opts.linetype,
+            opts.shift,
+        )
+        .unwrap();
+
+        let f = match filter_utils::mat_to_frame_rgb24(mat, width, height) {
+            Ok(value) => value,
+            Err(value) => return value,
+        };
+
+        Ok(filter::Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> std::result::Result<filter::FrameType, dve::Error> {
+        let opts: RectangleArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(dve::Error::AVError(err)),
+        };
+
+        if opts.img.unwrap_frame_type().format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+            return Err(dve::Error::AVError("Expected RGB24 frame".into()));
+        }
+
+        Ok(opts.img.unwrap_frame_type())
+    }
+}
+
+pub struct PutText {}
+
+struct PutTextArgs {
+    img: filter_utils::FrameArg,
+    text: String,
+    org: (i32, i32),
+    font_face: i32,
+    font_scale: f64,
+    color: [f64; 4],
+    thickness: i32,
+    linetype: i32,
+    bottom_left_origin: bool,
+}
+
+impl PutText {
+    fn args(
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> Result<PutTextArgs, String> {
+        let signature = filter_utils::FunctionSignature {
+            parameters: vec![
+                Parameter::Positional { name: "img" },
+                Parameter::Positional { name: "text" },
+                Parameter::Positional { name: "org" },
+                Parameter::Positional { name: "fontFace" },
+                Parameter::Positional { name: "fontScale" },
+                Parameter::Positional { name: "color" },
+                Parameter::PositionalOptional {
+                    name: "thickness",
+                    default_value: Val::Int(1),
+                },
+                Parameter::PositionalOptional {
+                    name: "lineType",
+                    default_value: Val::Int(8),
+                },
+                Parameter::PositionalOptional {
+                    name: "bottomLeftOrigin",
+                    default_value: Val::Bool(false),
+                },
+            ],
+        };
+
+        let kwargs = kwargs.clone();
+        let args: Vec<Val> = args.to_vec();
+        let parsed_args = filter_utils::parse_arguments(&signature, args, kwargs)?;
+
+        let img = match parsed_args.get("img") {
+            Some(Val::Frame(frame)) => filter_utils::FrameArg::Frame(frame.clone()),
+            Some(Val::FrameType(frame_type)) => {
+                filter_utils::FrameArg::FrameType(frame_type.clone())
+            }
+            x => {
+                dbg! {x};
+                return Err("Expected 'img' to be a Frame".into());
+            }
+        };
+
+        // text is a string
+        let text = match parsed_args.get("text") {
+            Some(Val::String(value)) => value.clone(),
+            _ => return Err("Expected 'text' to be a string".into()),
+        };
+
+        // org is a list of two integers
+        let org = filter_utils::get_point(&parsed_args, "org")?;
+
+        // fontFace is an integer
+        let font_face = match parsed_args.get("fontFace") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'fontFace' to be an integer".into()),
+        };
+
+        // fontScale is a float
+        let font_scale = match parsed_args.get("fontScale") {
+            Some(Val::Float(value)) => *value,
+            _ => return Err("Expected 'fontScale' to be a float".into()),
+        };
+
+        // color is a list of four floats
+        let color = filter_utils::get_color(&parsed_args)?;
+
+        // thickness is an integer
+        let thickness = match parsed_args.get("thickness") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'thickness' to be an integer".into()),
+        };
+
+        // lineType is an integer
+        let linetype = match parsed_args.get("lineType") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'lineType' to be an integer".into()),
+        };
+
+        // bottomLeftOrigin is a boolean
+        let bottom_left_origin = match parsed_args.get("bottomLeftOrigin") {
+            Some(Val::Bool(value)) => *value,
+            _ => return Err("Expected 'bottomLeftOrigin' to be a boolean".into()),
+        };
+
+        Ok(PutTextArgs {
+            img,
+            text,
+            org,
+            font_face,
+            font_scale,
+            color,
+            thickness,
+            linetype,
+            bottom_left_origin,
+        })
+    }
+}
+
+impl filter::Filter for PutText {
+    fn filter(
+        &self,
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> std::result::Result<filter::Frame, dve::Error> {
+        let opts: PutTextArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(dve::Error::AVError(err)),
+        };
+
+        let img = opts.img.unwrap_frame();
+        let (width, height) = (img.width, img.height);
+        debug_assert_eq!(img.format, ffi::AVPixelFormat_AV_PIX_FMT_RGB24);
+
+        let mut mat = filter_utils::frame_to_mat_rgb24(&img, width, height);
+
+        let org = opencv::core::Point::new(opts.org.0, opts.org.1);
+        let color =
+            opencv::core::Scalar::new(opts.color[0], opts.color[1], opts.color[2], opts.color[3]);
+
+        imgproc::put_text(
+            &mut mat,
+            &opts.text,
+            org,
+            opts.font_face,
+            opts.font_scale,
+            color,
+            opts.thickness,
+            opts.linetype,
+            opts.bottom_left_origin,
+        )
+        .unwrap();
+
+        let f = match filter_utils::mat_to_frame_rgb24(mat, width, height) {
+            Ok(value) => value,
+            Err(value) => return value,
+        };
+
+        Ok(filter::Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> std::result::Result<filter::FrameType, dve::Error> {
+        let opts: PutTextArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(dve::Error::AVError(err)),
+        };
+
+        if opts.img.unwrap_frame_type().format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+            return Err(dve::Error::AVError("Expected RGB24 frame".into()));
+        }
+
+        Ok(opts.img.unwrap_frame_type())
+    }
+}
+
+pub struct ArrowedLine {}
+
+struct ArrowedLineArgs {
+    img: FrameArg,
+    pt1: (i32, i32),
+    pt2: (i32, i32),
+    color: [f64; 4],
+    thickness: i32,
+    linetype: i32,
+    shift: i32,
+    tip_length: f64,
+}
+
+impl ArrowedLine {
+    fn args(
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> Result<ArrowedLineArgs, String> {
+        let signature = FunctionSignature {
+            parameters: vec![
+                Parameter::Positional { name: "img" },
+                Parameter::Positional { name: "pt1" },
+                Parameter::Positional { name: "pt2" },
+                Parameter::Positional { name: "color" },
+                Parameter::PositionalOptional {
+                    name: "thickness",
+                    default_value: Val::Int(1),
+                },
+                Parameter::PositionalOptional {
+                    name: "lineType",
+                    default_value: Val::Int(8),
+                },
+                Parameter::PositionalOptional {
+                    name: "shift",
+                    default_value: Val::Int(0),
+                },
+                Parameter::PositionalOptional {
+                    name: "tipLength",
+                    default_value: Val::Float(0.1),
+                },
+            ],
+        };
+
+        let kwargs = kwargs.clone();
+        let args = args.to_vec();
+        let parsed_args = parse_arguments(&signature, args, kwargs)?;
+
+        let img = match parsed_args.get("img") {
+            Some(Val::Frame(frame)) => FrameArg::Frame(frame.clone()),
+            Some(Val::FrameType(frame_type)) => FrameArg::FrameType(frame_type.clone()),
+            x => {
+                dbg! {x};
+                return Err("Expected 'img' to be a Frame".into());
+            }
+        };
+
+        // pt1 is a list of two integers
+        let pt1 = get_point(&parsed_args, "pt1")?;
+
+        // pt2 is a list of two integers
+        let pt2 = get_point(&parsed_args, "pt2")?;
+
+        // color is a list of four floats
+        let color = get_color(&parsed_args)?;
+
+        // thickness is an integer
+        let thickness = match parsed_args.get("thickness") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'thickness' to be an integer".into()),
+        };
+
+        // lineType is an integer
+        let linetype = match parsed_args.get("lineType") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'lineType' to be an integer".into()),
+        };
+
+        // shift is an integer
+        let shift = match parsed_args.get("shift") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'shift' to be an integer".into()),
+        };
+
+        // tipLength is a float
+        let tip_length = match parsed_args.get("tipLength") {
+            Some(Val::Float(value)) => *value,
+            _ => return Err("Expected 'tipLength' to be a float".into()),
+        };
+
+        Ok(ArrowedLineArgs {
+            img,
+            pt1,
+            pt2,
+            color,
+            thickness,
+            linetype,
+            shift,
+            tip_length,
+        })
+    }
+}
+
+impl filter::Filter for ArrowedLine {
+    fn filter(
+        &self,
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> std::result::Result<filter::Frame, dve::Error> {
+        let opts: ArrowedLineArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(dve::Error::AVError(err)),
+        };
+
+        let img = opts.img.unwrap_frame();
+        let (width, height) = (img.width, img.height);
+        debug_assert_eq!(img.format, ffi::AVPixelFormat_AV_PIX_FMT_RGB24);
+
+        let mut mat = frame_to_mat_rgb24(&img, width, height);
+
+        let pt1 = opencv::core::Point::new(opts.pt1.0, opts.pt1.1);
+        let pt2 = opencv::core::Point::new(opts.pt2.0, opts.pt2.1);
+        let color =
+            opencv::core::Scalar::new(opts.color[0], opts.color[1], opts.color[2], opts.color[3]);
+
+        imgproc::arrowed_line(
+            &mut mat,
+            pt1,
+            pt2,
+            color,
+            opts.thickness,
+            opts.linetype,
+            opts.shift,
+            opts.tip_length,
+        )
+        .unwrap();
+
+        let f = match mat_to_frame_rgb24(mat, width, height) {
+            Ok(value) => value,
+            Err(value) => return value,
+        };
+
+        Ok(filter::Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> std::result::Result<filter::FrameType, dve::Error> {
+        let opts: ArrowedLineArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(dve::Error::AVError(err)),
+        };
+
+        if opts.img.unwrap_frame_type().format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+            return Err(dve::Error::AVError("Expected RGB24 frame".into()));
+        }
+
+        Ok(opts.img.unwrap_frame_type())
+    }
+}
+
+pub struct Line {}
+
+struct LineArgs {
+    img: FrameArg,
+    pt1: (i32, i32),
+    pt2: (i32, i32),
+    color: [f64; 4],
+    thickness: i32,
+    linetype: i32,
+    shift: i32,
+}
+
+impl Line {
+    fn args(
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> Result<LineArgs, String> {
+        let signature = FunctionSignature {
+            parameters: vec![
+                Parameter::Positional { name: "img" },
+                Parameter::Positional { name: "pt1" },
+                Parameter::Positional { name: "pt2" },
+                Parameter::Positional { name: "color" },
+                Parameter::PositionalOptional {
+                    name: "thickness",
+                    default_value: Val::Int(1),
+                },
+                Parameter::PositionalOptional {
+                    name: "lineType",
+                    default_value: Val::Int(8),
+                },
+                Parameter::PositionalOptional {
+                    name: "shift",
+                    default_value: Val::Int(0),
+                },
+            ],
+        };
+
+        let kwargs = kwargs.clone();
+        let args = args.to_vec();
+        let parsed_args = parse_arguments(&signature, args, kwargs)?;
+
+        let img = match parsed_args.get("img") {
+            Some(Val::Frame(frame)) => FrameArg::Frame(frame.clone()),
+            Some(Val::FrameType(frame_type)) => FrameArg::FrameType(frame_type.clone()),
+            x => {
+                dbg! {x};
+                return Err("Expected 'img' to be a Frame".into());
+            }
+        };
+
+        // pt1 is a list of two integers
+        let pt1 = get_point(&parsed_args, "pt1")?;
+
+        // pt2 is a list of two integers
+        let pt2 = get_point(&parsed_args, "pt2")?;
+
+        // color is a list of four floats
+        let color = get_color(&parsed_args)?;
+
+        // thickness is an integer
+        let thickness = match parsed_args.get("thickness") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'thickness' to be an integer".into()),
+        };
+
+        // lineType is an integer
+        let linetype = match parsed_args.get("lineType") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'lineType' to be an integer".into()),
+        };
+
+        // shift is an integer
+        let shift = match parsed_args.get("shift") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'shift' to be an integer".into()),
+        };
+
+        Ok(LineArgs {
+            img,
+            pt1,
+            pt2,
+            color,
+            thickness,
+            linetype,
+            shift,
+        })
+    }
+}
+
+impl filter::Filter for Line {
+    fn filter(
+        &self,
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> std::result::Result<filter::Frame, dve::Error> {
+        let opts: LineArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(dve::Error::AVError(err)),
+        };
+
+        let img = opts.img.unwrap_frame();
+        let (width, height) = (img.width, img.height);
+        debug_assert_eq!(img.format, ffi::AVPixelFormat_AV_PIX_FMT_RGB24);
+
+        let mut mat = filter_utils::frame_to_mat_rgb24(&img, width, height);
+
+        let pt1 = opencv::core::Point::new(opts.pt1.0, opts.pt1.1);
+        let pt2 = opencv::core::Point::new(opts.pt2.0, opts.pt2.1);
+        let color =
+            opencv::core::Scalar::new(opts.color[0], opts.color[1], opts.color[2], opts.color[3]);
+
+        imgproc::line(
+            &mut mat,
+            pt1,
+            pt2,
+            color,
+            opts.thickness,
+            opts.linetype,
+            opts.shift,
+        )
+        .unwrap();
+
+        let f = match filter_utils::mat_to_frame_rgb24(mat, width, height) {
+            Ok(value) => value,
+            Err(value) => return value,
+        };
+
+        Ok(filter::Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> std::result::Result<filter::FrameType, dve::Error> {
+        let opts: LineArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(dve::Error::AVError(err)),
+        };
+
+        if opts.img.unwrap_frame_type().format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+            return Err(dve::Error::AVError("Expected RGB24 frame".into()));
+        }
+
+        Ok(opts.img.unwrap_frame_type())
+    }
+}
+
+pub struct Circle {}
+
+struct CircleArgs {
+    img: filter_utils::FrameArg,
+    center: (i32, i32),
+    radius: i32,
+    color: [f64; 4],
+    thickness: i32,
+    linetype: i32,
+    shift: i32,
+}
+
+impl Circle {
+    fn args(
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> Result<CircleArgs, String> {
+        let signature = filter_utils::FunctionSignature {
+            parameters: vec![
+                Parameter::Positional { name: "img" },
+                Parameter::Positional { name: "center" },
+                Parameter::Positional { name: "radius" },
+                Parameter::Positional { name: "color" },
+                Parameter::PositionalOptional {
+                    name: "thickness",
+                    default_value: Val::Int(1),
+                },
+                Parameter::PositionalOptional {
+                    name: "lineType",
+                    default_value: Val::Int(8),
+                },
+                Parameter::PositionalOptional {
+                    name: "shift",
+                    default_value: Val::Int(0),
+                },
+            ],
+        };
+
+        let kwargs = kwargs.clone();
+        let args = args.to_vec();
+        let parsed_args = filter_utils::parse_arguments(&signature, args, kwargs)?;
+
+        let img = match parsed_args.get("img") {
+            Some(Val::Frame(frame)) => filter_utils::FrameArg::Frame(frame.clone()),
+            Some(Val::FrameType(frame_type)) => {
+                filter_utils::FrameArg::FrameType(frame_type.clone())
+            }
+            x => {
+                dbg! {x};
+                return Err("Expected 'img' to be a Frame".into());
+            }
+        };
+
+        // center is a list of two integers
+        let center = filter_utils::get_point(&parsed_args, "center")?;
+
+        // radius is an integer
+        let radius = match parsed_args.get("radius") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'radius' to be an integer".into()),
+        };
+
+        // color is a list of four floats
+        let color = filter_utils::get_color(&parsed_args)?;
+
+        // thickness is an integer
+        let thickness = match parsed_args.get("thickness") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'thickness' to be an integer".into()),
+        };
+
+        // lineType is an integer
+        let linetype = match parsed_args.get("lineType") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'lineType' to be an integer".into()),
+        };
+
+        // shift is an integer
+        let shift = match parsed_args.get("shift") {
+            Some(Val::Int(value)) => *value as i32,
+            _ => return Err("Expected 'shift' to be an integer".into()),
+        };
+
+        Ok(CircleArgs {
+            img,
+            center,
+            radius,
+            color,
+            thickness,
+            linetype,
+            shift,
+        })
+    }
+}
+
+impl filter::Filter for Circle {
+    fn filter(
+        &self,
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> std::result::Result<filter::Frame, dve::Error> {
+        let opts: CircleArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(dve::Error::AVError(err)),
+        };
+
+        let img = opts.img.unwrap_frame();
+        let (width, height) = (img.width, img.height);
+        debug_assert_eq!(img.format, ffi::AVPixelFormat_AV_PIX_FMT_RGB24);
+
+        let mut mat = filter_utils::frame_to_mat_rgb24(&img, width, height);
+
+        let center = opencv::core::Point::new(opts.center.0, opts.center.1);
+        let color =
+            opencv::core::Scalar::new(opts.color[0], opts.color[1], opts.color[2], opts.color[3]);
+
+        imgproc::circle(
+            &mut mat,
+            center,
+            opts.radius,
+            color,
+            opts.thickness,
+            opts.linetype,
+            opts.shift,
+        )
+        .unwrap();
+
+        let f = match filter_utils::mat_to_frame_rgb24(mat, width, height) {
+            Ok(value) => value,
+            Err(value) => return value,
+        };
+
+        Ok(filter::Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[filter::Val],
+        kwargs: &BTreeMap<std::string::String, filter::Val>,
+    ) -> std::result::Result<filter::FrameType, dve::Error> {
+        let opts: CircleArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(dve::Error::AVError(err)),
+        };
+
+        if opts.img.unwrap_frame_type().format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+            return Err(dve::Error::AVError("Expected RGB24 frame".into()));
+        }
+
+        Ok(opts.img.unwrap_frame_type())
+    }
+}
+
+pub struct SetTo {}
+
+struct SetToArgs {
+    img: filter_utils::FrameArg,
+    color: [f64; 4],
+    mask: filter_utils::FrameArg,
+}
+
+impl SetTo {
+    fn args(
+        args: &[Val],
+        kwargs: &BTreeMap<std::string::String, Val>,
+    ) -> Result<SetToArgs, String> {
+        let signature = filter_utils::FunctionSignature {
+            parameters: vec![
+                Parameter::Positional { name: "img" },
+                Parameter::Positional { name: "color" },
+                Parameter::Positional { name: "mask" },
+            ],
+        };
+
+        let kwargs = kwargs.clone();
+        let args = args.to_vec();
+        let parsed_args = filter_utils::parse_arguments(&signature, args, kwargs)?;
+
+        let img = match parsed_args.get("img") {
+            Some(Val::Frame(frame)) => filter_utils::FrameArg::Frame(frame.clone()),
+            Some(Val::FrameType(frame_type)) => {
+                filter_utils::FrameArg::FrameType(frame_type.clone())
+            }
+            x => {
+                dbg! {x};
+                return Err("Expected 'img' to be a Frame".into());
+            }
+        };
+
+        let color = filter_utils::get_color(&parsed_args)?;
+
+        let mask = match parsed_args.get("mask") {
+            Some(Val::Frame(frame)) => filter_utils::FrameArg::Frame(frame.clone()),
+            Some(Val::FrameType(frame_type)) => {
+                filter_utils::FrameArg::FrameType(frame_type.clone())
+            }
+            x => {
+                dbg! {x};
+                return Err("Expected 'mask' to be a Frame".into());
+            }
+        };
+
+        Ok(SetToArgs { img, mask, color })
+    }
+}
+
+impl Filter for SetTo {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<std::string::String, Val>,
+    ) -> std::result::Result<Frame, crate::dve::Error> {
+        let opts: SetToArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(crate::dve::Error::AVError(err)),
+        };
+
+        let img = opts.img.unwrap_frame();
+        let mask = opts.mask.unwrap_frame();
+
+        let mut img_mat = filter_utils::frame_to_mat_rgb24(&img, img.width, img.height);
+        let mask_mat = filter_utils::frame_to_mat_gray8(&mask, mask.width, mask.height);
+
+        let color =
+            opencv::core::Scalar::new(opts.color[0], opts.color[1], opts.color[2], opts.color[3]);
+
+        // set all pixels in img_mat to color where mask_mat is not zero
+        img_mat.set_to(&color, &mask_mat).unwrap();
+
+        let f = match filter_utils::mat_to_frame_rgb24(img_mat, img.width, img.height) {
+            Ok(value) => value,
+            Err(value) => return value,
+        };
+
+        Ok(Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<std::string::String, Val>,
+    ) -> std::result::Result<FrameType, crate::dve::Error> {
+        let opts: SetToArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(crate::dve::Error::AVError(err)),
+        };
+
+        // check img is RGB24
+        if opts.img.unwrap_frame_type().format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+            return Err(crate::dve::Error::FilterInternalError(
+                "Expected img to be an RGB24 frame".into(),
+            ));
+        }
+
+        // check mask is grayscale
+        if opts.mask.unwrap_frame_type().format != ffi::AVPixelFormat_AV_PIX_FMT_GRAY8 {
+            return Err(crate::dve::Error::FilterInternalError(
+                "Expected mask to be a grayscale frame".into(),
+            ));
+        }
+
+        // check mask is same size as img
+        if opts.img.unwrap_frame_type().width != opts.mask.unwrap_frame_type().width
+            || opts.img.unwrap_frame_type().height != opts.mask.unwrap_frame_type().height
+        {
+            return Err(crate::dve::Error::FilterInternalError(
+                "Expected mask to be the same size as img".into(),
+            ));
+        }
+
+        Ok(opts.img.unwrap_frame_type())
+    }
+}
+
+pub struct AddWeighted {}
+
+struct AddWeightedArgs {
+    src1: filter_utils::FrameArg,
+    alpha: f64,
+    src2: filter_utils::FrameArg,
+    beta: f64,
+    gamma: f64,
+}
+
+impl AddWeighted {
+    fn args(
+        args: &[Val],
+        kwargs: &BTreeMap<std::string::String, Val>,
+    ) -> Result<AddWeightedArgs, String> {
+        let signature = filter_utils::FunctionSignature {
+            parameters: vec![
+                Parameter::Positional { name: "src1" },
+                Parameter::Positional { name: "alpha" },
+                Parameter::Positional { name: "src2" },
+                Parameter::Positional { name: "beta" },
+                Parameter::Positional { name: "gamma" },
+            ],
+        };
+
+        let kwargs = kwargs.clone();
+        let args = args.to_vec();
+        let parsed_args = filter_utils::parse_arguments(&signature, args, kwargs)?;
+
+        let src1 = match parsed_args.get("src1") {
+            Some(Val::Frame(frame)) => filter_utils::FrameArg::Frame(frame.clone()),
+            Some(Val::FrameType(frame_type)) => {
+                filter_utils::FrameArg::FrameType(frame_type.clone())
+            }
+            x => {
+                dbg! {x};
+                return Err("Expected 'src1' to be a Frame".into());
+            }
+        };
+
+        let alpha = match parsed_args.get("alpha") {
+            Some(Val::Float(value)) => *value,
+            _ => return Err("Expected 'alpha' to be a float".into()),
+        };
+
+        let src2 = match parsed_args.get("src2") {
+            Some(Val::Frame(frame)) => filter_utils::FrameArg::Frame(frame.clone()),
+            Some(Val::FrameType(frame_type)) => {
+                filter_utils::FrameArg::FrameType(frame_type.clone())
+            }
+            x => {
+                dbg! {x};
+                return Err("Expected 'src2' to be a Frame".into());
+            }
+        };
+
+        let beta = match parsed_args.get("beta") {
+            Some(Val::Float(value)) => *value,
+            _ => return Err("Expected 'beta' to be a float".into()),
+        };
+
+        let gamma = match parsed_args.get("gamma") {
+            Some(Val::Float(value)) => *value,
+            _ => return Err("Expected 'gamma' to be a float".into()),
+        };
+
+        Ok(AddWeightedArgs {
+            src1,
+            alpha,
+            src2,
+            beta,
+            gamma,
+        })
+    }
+}
+
+impl Filter for AddWeighted {
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<std::string::String, Val>,
+    ) -> std::result::Result<Frame, crate::dve::Error> {
+        let opts: AddWeightedArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(crate::dve::Error::AVError(err)),
+        };
+
+        let src1 = opts.src1.unwrap_frame();
+        let src2 = opts.src2.unwrap_frame();
+
+        let (width, height) = (src1.width, src1.height);
+        debug_assert_eq!(src1.format, ffi::AVPixelFormat_AV_PIX_FMT_RGB24);
+        debug_assert_eq!(src2.format, ffi::AVPixelFormat_AV_PIX_FMT_RGB24);
+
+        let src1_mat = filter_utils::frame_to_mat_rgb24(&src1, width, height);
+        let src2_mat = filter_utils::frame_to_mat_rgb24(&src2, width, height);
+
+        let mut out_mat = opencv::core::Mat::new_nd_with_default(
+            &[height, width, 3],
+            opencv::core::CV_8UC3,
+            opencv::core::Scalar::all(0.0),
+        )
+        .unwrap();
+
+        opencv::core::add_weighted(
+            &src1_mat,
+            opts.alpha,
+            &src2_mat,
+            opts.beta,
+            opts.gamma,
+            &mut out_mat,
+            -1,
+        )
+        .unwrap();
+
+        assert_eq!(out_mat.rows(), { height });
+        assert_eq!(out_mat.cols(), { width });
+        assert_eq!(out_mat.channels(), 3);
+
+        let f = match filter_utils::mat_to_frame_rgb24(out_mat, width, height) {
+            Ok(value) => value,
+            Err(value) => return value,
+        };
+
+        Ok(Frame::new(AVFrame { inner: f }))
+    }
+
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<std::string::String, Val>,
+    ) -> std::result::Result<FrameType, crate::dve::Error> {
+        let opts: AddWeightedArgs = match Self::args(args, kwargs) {
+            Ok(args) => args,
+            Err(err) => return Err(crate::dve::Error::AVError(err)),
+        };
+
+        // check src1 is RGB24
+        if opts.src1.unwrap_frame_type().format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+            return Err(crate::dve::Error::FilterInternalError(
+                "Expected src1 to be an RGB24 frame".into(),
+            ));
+        }
+
+        // check src2 is RGB24
+        if opts.src2.unwrap_frame_type().format != ffi::AVPixelFormat_AV_PIX_FMT_RGB24 {
+            return Err(crate::dve::Error::FilterInternalError(
+                "Expected src2 to be an RGB24 frame".into(),
+            ));
+        }
+
+        // check src1 and src2 are the same size
+        if opts.src1.unwrap_frame_type().width != opts.src2.unwrap_frame_type().width
+            || opts.src1.unwrap_frame_type().height != opts.src2.unwrap_frame_type().height
+        {
+            return Err(crate::dve::Error::FilterInternalError(
+                "Expected src1 and src2 to be the same size".into(),
+            ));
+        }
+
+        Ok(opts.src1.unwrap_frame_type())
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/filter/filter_utils.rs.html b/src/vidformer/filter/filter_utils.rs.html new file mode 100644 index 0000000..90cb776 --- /dev/null +++ b/src/vidformer/filter/filter_utils.rs.html @@ -0,0 +1,775 @@ +filter_utils.rs - source

vidformer/filter/
filter_utils.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
use opencv::core::MatTrait;
+
+use super::*;
+use std::collections::BTreeMap;
+
+use super::Val;
+
+#[derive(Clone, Debug)]
+pub(crate) enum Parameter {
+    Positional {
+        name: &'static str,
+    },
+    PositionalOptional {
+        name: &'static str,
+        default_value: Val,
+    },
+    // VarArgs {
+    //     name: &'static str,
+    // },
+    // KeywordOnly {
+    //     name: &'static str,
+    // },
+    // KeywordOnlyOptional {
+    //     name: &'static str,
+    //     default_value: Val,
+    // },
+    // KwArgs {
+    //     name: &'static str,
+    // },
+}
+
+pub(crate) struct FunctionSignature {
+    pub(crate) parameters: Vec<Parameter>,
+}
+
+pub(crate) fn parse_arguments(
+    signature: &FunctionSignature,
+    args: Vec<Val>,
+    mut kwargs: std::collections::BTreeMap<String, Val>,
+) -> Result<std::collections::BTreeMap<&'static str, Val>, String> {
+    let mut parsed_args: BTreeMap<&'static str, Val> = std::collections::BTreeMap::new();
+    let mut arg_iter = args.into_iter();
+    // let mut varargs = Vec::new();
+    // let mut keyword_only: bool = false;
+
+    for param in &signature.parameters {
+        match param {
+            Parameter::Positional { name } => {
+                // assert!(
+                //     !keyword_only,
+                //     "Positional argument after keyword-only argument"
+                // );
+                if let Some(val) = arg_iter.next() {
+                    parsed_args.insert(name, val);
+                } else if let Some(val) = kwargs.remove(*name) {
+                    parsed_args.insert(name, val);
+                } else {
+                    return Err(format!("Missing required positional argument '{}'", name));
+                }
+            }
+            Parameter::PositionalOptional {
+                name,
+                default_value,
+            } => {
+                // assert!(
+                //     !keyword_only,
+                //     "PositionalOptional argument after keyword-only argument"
+                // );
+                if let Some(val) = arg_iter.next() {
+                    parsed_args.insert(name, val);
+                } else if let Some(val) = kwargs.remove(*name) {
+                    parsed_args.insert(name, val);
+                } else {
+                    parsed_args.insert(name, default_value.clone());
+                }
+            } // Parameter::VarArgs { name } => {
+              //     assert!(
+              //         !keyword_only,
+              //         "VarArgs argument after keyword-only argument"
+              //     );
+              //     for val in arg_iter.by_ref() {
+              //         varargs.push(val);
+              //     }
+              //     parsed_args.insert(name, Val::List(varargs.clone()));
+              //     keyword_only = true; // Everything after *args is keyword-only
+              // }
+              // Parameter::KeywordOnly { name } => {
+              //     if let Some(val) = kwargs.remove(*name) {
+              //         parsed_args.insert(name, val);
+              //     } else {
+              //         return Err(format!("Missing required keyword-only argument '{}'", name));
+              //     }
+              // }
+              // Parameter::KeywordOnlyOptional {
+              //     name,
+              //     default_value,
+              // } => {
+              //     if let Some(val) = kwargs.remove(*name) {
+              //         parsed_args.insert(name, val);
+              //     } else {
+              //         parsed_args.insert(name, default_value.clone());
+              //     }
+              // }
+              // Parameter::KwArgs { name: _ } => {
+              //     todo!()
+              // }
+        }
+    }
+
+    // Check for any remaining positional arguments
+    if arg_iter.next().is_some() {
+        return Err("Too many positional arguments".into());
+    }
+
+    // Check for any unexpected keyword arguments
+    if !kwargs.is_empty() {
+        return Err(format!(
+            "Got unexpected keyword arguments: {:?}",
+            kwargs.keys()
+        ));
+    }
+
+    Ok(parsed_args)
+}
+
+pub(crate) fn get_color(parsed_args: &BTreeMap<&'static str, Val>) -> Result<[f64; 4], String> {
+    let color = match parsed_args.get("color") {
+        Some(Val::List(list)) => {
+            if list.len() != 4 {
+                return Err("Expected 'color' to be a list of four floats".into());
+            }
+            match (
+                list[0].clone(),
+                list[1].clone(),
+                list[2].clone(),
+                list[3].clone(),
+            ) {
+                (Val::Float(r), Val::Float(g), Val::Float(b), Val::Float(a)) => [r, g, b, a],
+                _ => return Err("Expected 'color' to be a list of four floats".into()),
+            }
+        }
+        _ => return Err("Expected 'color' to be a list of four floats".into()),
+    };
+    Ok(color)
+}
+
+pub(crate) fn get_point(
+    parsed_args: &BTreeMap<&'static str, Val>,
+    key: &str,
+) -> Result<(i32, i32), String> {
+    let pt = match parsed_args.get(key) {
+        Some(Val::List(list)) => {
+            if list.len() != 2 {
+                return Err(format!("Expected '{key}' to be a list of two integers"));
+            }
+            match (list[0].clone(), list[1].clone()) {
+                (Val::Int(x), Val::Int(y)) => (x as i32, y as i32),
+                _ => return Err(format!("Expected '{key}' to be a list of two integers")),
+            }
+        }
+        _ => return Err(format!("Expected '{key}' to be a list of two integers")),
+    };
+    Ok(pt)
+}
+
+pub(crate) enum FrameArg {
+    Frame(Frame),
+    FrameType(FrameType),
+}
+
+impl FrameArg {
+    pub(crate) fn unwrap_frame_type(&self) -> FrameType {
+        match self {
+            FrameArg::Frame(_frame) => panic!(),
+            FrameArg::FrameType(frame_type) => frame_type.clone(),
+        }
+    }
+
+    pub(crate) fn unwrap_frame(&self) -> Frame {
+        match self {
+            FrameArg::Frame(frame) => frame.clone(),
+            FrameArg::FrameType(_frame_type) => panic!(),
+        }
+    }
+}
+
+pub(crate) fn mat_to_frame_rgb24(
+    mat: opencv::prelude::Mat,
+    width: i32,
+    height: i32,
+) -> Result<*mut ffi::AVFrame, Result<Frame, crate::dve::Error>> {
+    let f = unsafe { ffi::av_frame_alloc() };
+    if f.is_null() {
+        return Err(Err(crate::dve::Error::AVError(
+            "Failed to allocate frame".into(),
+        )));
+    }
+
+    debug_assert_eq!(mat.elem_size().unwrap(), 3);
+    debug_assert_eq!(mat.channels(), 3);
+    debug_assert_eq!(mat.size().unwrap().height, height);
+    debug_assert_eq!(mat.size().unwrap().width, width);
+    unsafe {
+        (*f).width = width;
+        (*f).height = height;
+        (*f).format = ffi::AVPixelFormat_AV_PIX_FMT_RGB24;
+
+        if ffi::av_frame_get_buffer(f, 0) < 0 {
+            panic!("ERROR could not allocate frame data");
+        }
+    }
+
+    if unsafe { (*f).linesize[0] } == width * 3 {
+        // no padding, just copy the data
+        unsafe {
+            let src = mat.data();
+            let dst = (*f).data[0];
+            std::ptr::copy_nonoverlapping(src, dst, width as usize * height as usize * 3);
+        }
+    } else {
+        // there is padding, copy line by line
+        debug_assert!(unsafe { (*f).linesize[0] } > width * 3);
+        unsafe {
+            let mut src = mat.data();
+            let mut dst = (*f).data[0];
+            for _ in 0..height {
+                std::ptr::copy_nonoverlapping(src, dst, width as usize * 3);
+                src = src.add((*f).linesize[0] as usize);
+                dst = dst.add(width as usize * 3);
+            }
+        }
+    }
+    Ok(f)
+}
+
+pub(crate) fn frame_to_mat_rgb24(img: &Frame, width: i32, height: i32) -> opencv::prelude::Mat {
+    debug_assert!(img.format == ffi::AVPixelFormat_AV_PIX_FMT_RGB24);
+    debug_assert_eq!(img.height, height);
+    debug_assert_eq!(img.width, width);
+    debug_assert_eq!(
+        unsafe { (*(img.inner.inner)).format },
+        ffi::AVPixelFormat_AV_PIX_FMT_RGB24
+    );
+    debug_assert_eq!(unsafe { (*(img.inner.inner)).width }, width);
+    debug_assert_eq!(unsafe { (*(img.inner.inner)).height }, height);
+
+    let img: ffi::AVFrame = unsafe { *img.inner.inner };
+
+    let mut mat =
+        unsafe { opencv::core::Mat::new_rows_cols(height, width, opencv::core::CV_8UC3) }.unwrap();
+
+    debug_assert!(mat.elem_size().unwrap() == 3);
+    debug_assert!(mat.channels() == 3);
+    debug_assert!(mat.size().unwrap().height == height);
+    debug_assert!(mat.size().unwrap().width == width);
+    debug_assert!(mat.is_continuous());
+
+    if img.linesize[0] == width * 3 {
+        // no padding, just copy the data
+        unsafe {
+            let src = img.data[0];
+            let dst = mat.data_mut();
+            std::ptr::copy_nonoverlapping(src, dst, width as usize * height as usize * 3);
+        }
+    } else {
+        // there is padding, copy line by line
+        debug_assert!(img.linesize[0] > width * 3);
+        unsafe {
+            let mut src = img.data[0];
+            let mut dst = mat.data_mut();
+            for _ in 0..height {
+                std::ptr::copy_nonoverlapping(src, dst, width as usize * 3);
+                src = src.add(img.linesize[0] as usize);
+                dst = dst.add(width as usize * 3);
+            }
+        }
+    }
+
+    mat
+}
+
+pub(crate) fn frame_to_mat_gray8(img: &Frame, width: i32, height: i32) -> opencv::prelude::Mat {
+    debug_assert!(img.format == ffi::AVPixelFormat_AV_PIX_FMT_GRAY8);
+    debug_assert_eq!(img.height, height);
+    debug_assert_eq!(img.width, width);
+    debug_assert_eq!(
+        unsafe { (*(img.inner.inner)).format },
+        ffi::AVPixelFormat_AV_PIX_FMT_GRAY8
+    );
+    debug_assert_eq!(unsafe { (*(img.inner.inner)).width }, width);
+    debug_assert_eq!(unsafe { (*(img.inner.inner)).height }, height);
+
+    let img: ffi::AVFrame = unsafe { *img.inner.inner };
+
+    let mut mat =
+        unsafe { opencv::core::Mat::new_rows_cols(height, width, opencv::core::CV_8UC1) }.unwrap();
+
+    debug_assert!(mat.elem_size().unwrap() == 1);
+    debug_assert!(mat.channels() == 1);
+    debug_assert!(mat.size().unwrap().height == height);
+    debug_assert!(mat.size().unwrap().width == width);
+    debug_assert!(mat.is_continuous());
+
+    if img.linesize[0] == width {
+        // no padding, just copy the data
+        unsafe {
+            let src = img.data[0];
+            let dst = mat.data_mut();
+            std::ptr::copy_nonoverlapping(src, dst, width as usize * height as usize);
+        }
+    } else {
+        // there is padding, copy line by line
+        debug_assert!(img.linesize[0] > width);
+        unsafe {
+            let mut src = img.data[0];
+            let mut dst = mat.data_mut();
+            for _ in 0..height {
+                std::ptr::copy_nonoverlapping(src, dst, width as usize);
+                src = src.add(img.linesize[0] as usize);
+                dst = dst.add(width as usize);
+            }
+        }
+    }
+
+    mat
+}
+
+#[cfg(test)]
+mod tests {
+    use opencv::core::Scalar;
+    use opencv::prelude::Mat;
+    use opencv::prelude::MatTraitConst;
+    use rusty_ffmpeg::ffi;
+
+    #[test]
+    fn test_packed_layout_rgb24() {
+        // we do some sharing of buffers between libav and opencv so we need to make sure that
+        // the layout of the data is the same
+
+        let num_planes =
+            unsafe { ffi::av_pix_fmt_count_planes(ffi::AVPixelFormat_AV_PIX_FMT_RGB24) };
+        assert_eq!(num_planes, 1);
+
+        let width = 1920;
+        let height = 1080;
+        let size = (width as usize) * (height as usize) * 3;
+
+        let frame_encoded_size_all_planes = unsafe {
+            ffi::av_image_get_buffer_size(ffi::AVPixelFormat_AV_PIX_FMT_RGB24, width, height, 1)
+        };
+
+        assert_eq!(size, frame_encoded_size_all_planes as usize);
+
+        // make sure mat data buffer is the same size as the frame buffer
+        let color = Scalar::new(255.0, 0.0, 0.0, 0.0);
+        let mat =
+            Mat::new_rows_cols_with_default(height, width, opencv::core::CV_8UC3, color).unwrap();
+
+        assert_eq!(size, mat.total() * mat.elem_size().unwrap());
+        assert!(mat.is_continuous());
+    }
+
+    #[test]
+    fn test_packed_layout_gray8() {
+        let num_planes =
+            unsafe { ffi::av_pix_fmt_count_planes(ffi::AVPixelFormat_AV_PIX_FMT_GRAY8) };
+        assert_eq!(num_planes, 1);
+
+        let width = 1920;
+        let height = 1080;
+        let size = (width as usize) * (height as usize);
+
+        let frame_encoded_size_all_planes = unsafe {
+            ffi::av_image_get_buffer_size(ffi::AVPixelFormat_AV_PIX_FMT_GRAY8, width, height, 1)
+        };
+
+        assert_eq!(size, frame_encoded_size_all_planes as usize);
+
+        // make sure mat data buffer is the same size as the frame buffer
+        let color = Scalar::new(255.0, 0.0, 0.0, 0.0);
+        let mat =
+            Mat::new_rows_cols_with_default(height, width, opencv::core::CV_8UC1, color).unwrap();
+
+        assert_eq!(size, mat.total() * mat.elem_size().unwrap());
+        assert!(mat.is_continuous());
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/lib.rs.html b/src/vidformer/lib.rs.html new file mode 100644 index 0000000..0188329 --- /dev/null +++ b/src/vidformer/lib.rs.html @@ -0,0 +1,51 @@ +lib.rs - source

vidformer/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
//! [vidformer](https://github.com/ixlab/vidformer) is a core video synthesis/transformation library.
+//! It handles the movement, control flow, and processing of video and conventional (non-video) data.
+//!
+//! **Quick links:**
+//! * [📦 Crates.io](https://crates.io/crates/vidformer)
+//! * [📘 Documentation](https://ixlab.github.io/vidformer/vidformer/)
+//! * [🧑‍💻 Source Code](https://github.com/ixlab/vidformer/tree/main/vidformer/)
+
+pub mod array;
+pub mod filter;
+pub mod service;
+pub mod sir;
+pub mod source;
+pub mod spec;
+
+pub(crate) mod av;
+mod dve;
+mod pool;
+mod util;
+
+pub use dve::{
+    create_spec_hls, run, validate, Config, Context, EncoderConfig, Error, Range, RangeTsFormat,
+    Stats,
+};
+pub use util::{codecs, init, CodecDescriptor};
+
\ No newline at end of file diff --git a/src/vidformer/pool.rs.html b/src/vidformer/pool.rs.html new file mode 100644 index 0000000..663f0c5 --- /dev/null +++ b/src/vidformer/pool.rs.html @@ -0,0 +1,831 @@ +pool.rs - source

vidformer/
pool.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
use crate::dve::IFrameRef;
+use crate::dve::{AVFrame, Config, Context, SourceRef};
+use std::fmt::Debug;
+use std::{
+    collections::{BTreeMap, BTreeSet},
+    sync::Arc,
+};
+
+const F_NOT_USED: usize = usize::MAX;
+
+pub(crate) struct Pool {
+    done_gens_recent: BTreeSet<usize>,
+    done_gens_past: usize, // If a generation is less than this it is done
+    next_gen: usize,
+    members: BTreeMap<IFrameRef, Arc<AVFrame>>,
+    pub(crate) decoders: BTreeMap<String, crate::dve::DecoderState>,
+    pub(crate) finished_unjoined_decoders: BTreeSet<String>,
+    pub(crate) terminate_decoders: bool,
+
+    iframes_per_oframe: Vec<BTreeSet<IFrameRef>>,
+    iframe_refs_in_out_idx: BTreeMap<IFrameRef, BTreeSet<usize>>,
+    dve_context: Arc<Context>,
+    dve_config: Arc<Config>,
+}
+
+impl Pool {
+    pub(crate) fn new(
+        iframes_per_oframe: Vec<BTreeSet<IFrameRef>>,
+        iframe_refs_in_out_idx: BTreeMap<IFrameRef, BTreeSet<usize>>,
+        dve_context: Arc<Context>,
+        dve_config: Arc<Config>,
+    ) -> Result<Self, crate::Error> {
+        if dve_config.decode_pool_size == 0 {
+            return Err(crate::Error::ConfigError(
+                "decode_pool_size must be greater than 0".to_string(),
+            ));
+        }
+
+        let mut out = Pool {
+            done_gens_recent: BTreeSet::new(),
+            done_gens_past: 0,
+            next_gen: 0,
+            members: BTreeMap::new(),
+            decoders: BTreeMap::new(),
+            finished_unjoined_decoders: BTreeSet::new(),
+            terminate_decoders: false,
+            iframes_per_oframe,
+            iframe_refs_in_out_idx,
+            dve_context,
+            dve_config,
+        };
+        while out.plan_gen() {}
+        Ok(out)
+    }
+
+    fn next_needed_gen(&self, frame: &IFrameRef) -> usize {
+        let frame_uses = match self.iframe_refs_in_out_idx.get(frame) {
+            Some(uses) => uses,
+            None => return F_NOT_USED,
+        };
+        // TODO: We could throw a binary search in here to speed up cases where there are many uses of a frame, such as a watermark image
+        for frame_use_gen in frame_uses {
+            if frame_use_gen >= &self.done_gens_past
+                && !self.done_gens_recent.contains(frame_use_gen)
+            {
+                return *frame_use_gen;
+            }
+        }
+        F_NOT_USED
+    }
+
+    fn decoder_next_needed_gen(&self, decoder_id: &str) -> usize {
+        let decoder = self.decoders.get(decoder_id).unwrap();
+        let mut next_needed_gen = F_NOT_USED;
+        for frame in &decoder.future_frames {
+            let frame_next_needed = self.next_needed_gen(&IFrameRef {
+                sourceref: decoder.source.clone(),
+                pts: *frame,
+            });
+            if frame_next_needed < next_needed_gen {
+                next_needed_gen = frame_next_needed;
+            }
+        }
+        next_needed_gen
+    }
+
+    fn frame_gop(&self, frame: &IFrameRef) -> usize {
+        let source = self.dve_context.sources.get(&frame.sourceref).unwrap();
+        debug_assert!(source.ts.binary_search(&frame.pts).is_ok());
+        match source.keys.binary_search(&frame.pts) {
+            Ok(i) => i,
+            Err(i) => i - 1, // i is the index of the first element greater than frame.pts
+        }
+    }
+
+    pub(crate) fn new_decoder_gop(&self) -> Option<(SourceRef, usize)> {
+        debug_assert!(self.decoders.len() <= self.dve_config.decoders);
+        if self.decoders.len() == self.dve_config.decoders {
+            return None;
+        }
+        let need_set = self
+            .need_set()
+            .into_iter()
+            .cloned()
+            .collect::<BTreeSet<_>>();
+        let future_set: BTreeSet<IFrameRef> = self.future_set();
+        let basis_frames: BTreeSet<IFrameRef> = need_set
+            .difference(&self.members.keys().cloned().collect())
+            .cloned()
+            .collect::<BTreeSet<_>>()
+            .difference(&future_set)
+            .cloned()
+            .collect();
+
+        if !basis_frames.is_empty() {
+            let mut iter = basis_frames.iter();
+            let mut soonest_needed_basis_frame = iter.next().unwrap();
+            let mut soonest_needed_basis_frame_next_needed =
+                self.next_needed_gen(soonest_needed_basis_frame);
+
+            for frame in iter {
+                let candidate_frame_next_needed = self.next_needed_gen(frame);
+                if candidate_frame_next_needed < soonest_needed_basis_frame_next_needed {
+                    soonest_needed_basis_frame = frame;
+                    soonest_needed_basis_frame_next_needed = candidate_frame_next_needed;
+                }
+            }
+
+            let gop_id = self.frame_gop(soonest_needed_basis_frame);
+            Some((soonest_needed_basis_frame.sourceref.clone(), gop_id))
+        } else {
+            None
+        }
+    }
+
+    fn eviction_set(
+        &self,
+        size: usize,
+        next_need_set: &BTreeSet<IFrameRef>,
+    ) -> BTreeSet<IFrameRef> {
+        struct FrameEvictionCandidate<'b> {
+            needed_gen: usize,
+            frame_ts: &'b IFrameRef,
+        }
+        impl Ord for FrameEvictionCandidate<'_> {
+            fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+                self.needed_gen.cmp(&other.needed_gen)
+            }
+        }
+        impl PartialOrd for FrameEvictionCandidate<'_> {
+            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+                Some(self.cmp(other))
+            }
+        }
+        impl Eq for FrameEvictionCandidate<'_> {}
+        impl PartialEq for FrameEvictionCandidate<'_> {
+            fn eq(&self, other: &Self) -> bool {
+                self.needed_gen == other.needed_gen
+            }
+        }
+
+        let mut heap = std::collections::BinaryHeap::new();
+        for frame_ts in self.members.keys() {
+            if !next_need_set.contains(frame_ts) {
+                heap.push(FrameEvictionCandidate {
+                    needed_gen: self.next_needed_gen(frame_ts),
+                    frame_ts,
+                });
+            }
+        }
+
+        debug_assert!(heap.len() >= size);
+        let mut out = BTreeSet::new();
+        for _ in 0..size {
+            let evicted = heap.pop().unwrap();
+            out.insert(evicted.frame_ts.clone());
+        }
+        out
+    }
+
+    pub(crate) fn should_stall(&self, decoder_id: &str) -> bool {
+        // Is there a frame in the need set which is not in the members set but is in our future set?
+        // If not, stall
+
+        let decoder = self.decoders.get(decoder_id).unwrap();
+
+        let need_set = self
+            .need_set()
+            .into_iter()
+            .cloned()
+            .collect::<BTreeSet<_>>();
+        let dec_future_set = decoder.future_iframerefs();
+        let members_set = self.members.keys().cloned().collect::<BTreeSet<_>>();
+
+        let missing_frames = need_set
+            .difference(&members_set)
+            .cloned()
+            .collect::<BTreeSet<_>>();
+
+        missing_frames.intersection(&dec_future_set).count() == 0
+    }
+
+    pub(crate) fn decoded(&mut self, decoder_id: &str, frame: IFrameRef, avframe: Arc<AVFrame>) {
+        debug_assert!(self.members.len() <= self.dve_config.decode_pool_size);
+        debug_assert!(!self.should_stall(decoder_id));
+
+        if self.members.contains_key(&frame) {
+            // Frame already present
+            return;
+        }
+
+        let need_set: BTreeSet<IFrameRef> = self.need_set().into_iter().cloned().collect();
+
+        if need_set.contains(&frame) || self.members.len() < self.dve_config.decode_pool_size {
+            // If the pool is full evict a cache frame
+            if self.members.len() == self.dve_config.decode_pool_size {
+                let evict_set = self.eviction_set(1, &need_set);
+                debug_assert_eq!(evict_set.len(), 1);
+                for frame_ts in evict_set {
+                    self.members.remove(&frame_ts);
+                }
+            }
+            self.members.insert(frame, avframe);
+        } else {
+            // See if we can evict a frame to make room
+            let f_next_need = self.next_needed_gen(&frame);
+            if f_next_need < F_NOT_USED {
+                let mut least_needed_pool_frame: Option<IFrameRef> = None;
+                let mut least_needed_pool_frame_next_needed = F_NOT_USED;
+
+                for pool_frame in self.members.keys() {
+                    if !need_set.contains(pool_frame) {
+                        if least_needed_pool_frame.is_some() {
+                            let pool_frame_next_needed = self.next_needed_gen(pool_frame);
+                            if pool_frame_next_needed > least_needed_pool_frame_next_needed {
+                                least_needed_pool_frame = Some(pool_frame.clone());
+                                least_needed_pool_frame_next_needed = pool_frame_next_needed;
+                            }
+                        } else {
+                            least_needed_pool_frame = Some(pool_frame.clone());
+                            least_needed_pool_frame_next_needed = self.next_needed_gen(pool_frame);
+                        }
+                    }
+                }
+
+                if f_next_need < least_needed_pool_frame_next_needed {
+                    log::info!("Evicting frame {:?} (needed in gen {}) for sooner-needed frame {:?} (needed in gen {})", least_needed_pool_frame, least_needed_pool_frame_next_needed, frame, f_next_need);
+                    self.members.remove(&least_needed_pool_frame.unwrap());
+                    self.members.insert(frame, avframe);
+                }
+            }
+        }
+
+        debug_assert!(self.members.len() <= self.dve_config.decode_pool_size);
+    }
+
+    pub(crate) fn should_decoder_abandon(&self, decoder_id: &str) -> bool {
+        if self.decoders.len() < self.dve_config.decoders || !self.should_stall(decoder_id) {
+            return false;
+        }
+
+        let dec_next_needed_gen = self.decoder_next_needed_gen(decoder_id);
+
+        // check that there is a frame we should create a new decoder for
+        let mut found_sooner_basis_frame = false;
+        let future_set = self.future_set();
+        for frame in self.need_set() {
+            if self.members.contains_key(frame) || future_set.contains(frame) {
+                continue;
+            }
+            let frame_next_needed_gen = self.next_needed_gen(frame);
+            if frame_next_needed_gen < dec_next_needed_gen {
+                found_sooner_basis_frame = true;
+                break;
+            }
+        }
+        if !found_sooner_basis_frame {
+            return false;
+        }
+
+        // check if all other decoders have a lower or equal next needed gen
+        // aka make sure this is the least-soonest-needed decoder
+        for other_decoder_id in self.decoders.keys() {
+            if other_decoder_id == decoder_id {
+                continue;
+            }
+            let other_dec_next_needed_gen = self.decoder_next_needed_gen(other_decoder_id);
+            if other_dec_next_needed_gen > dec_next_needed_gen {
+                return false;
+            }
+        }
+
+        true
+    }
+
+    pub(crate) fn future_set(&self) -> BTreeSet<IFrameRef> {
+        let mut out = BTreeSet::new();
+        for decoder in self.decoders.values() {
+            out.extend(decoder.future_frames.iter().map(|t| IFrameRef {
+                sourceref: decoder.source.clone(),
+                pts: *t,
+            }));
+        }
+        out
+    }
+
+    fn plan_gen(&mut self) -> bool {
+        debug_assert!(self.next_gen <= self.iframes_per_oframe.len());
+        if self.next_gen == self.iframes_per_oframe.len() {
+            return false;
+        }
+
+        let number_of_active_gens =
+            self.next_gen - self.done_gens_past - self.done_gens_recent.len();
+        debug_assert_eq!(number_of_active_gens, self.active_gens().len());
+        if number_of_active_gens >= self.dve_config.decoder_view {
+            return false;
+        }
+
+        let mut next_need_set: BTreeSet<IFrameRef> =
+            { self.need_set().iter().map(|a| (*a).clone()).collect() };
+        next_need_set.extend(
+            self.iframes_per_oframe[self.next_gen]
+                .iter()
+                .map(|a| (*a).clone()),
+        );
+
+        if next_need_set.len() > self.dve_config.decode_pool_size {
+            // not enough space in the pool even with evictions
+            return false;
+        }
+
+        // Enough space, but check if we need to evict some frames first
+        let current_members = self.members.keys().map(|a| (*a).clone()).collect();
+        let next_need_set_union_current_members: BTreeSet<_> =
+            next_need_set.union(&current_members).cloned().collect();
+        if next_need_set_union_current_members.len() > self.dve_config.decode_pool_size {
+            let needed_evictions =
+                next_need_set_union_current_members.len() - self.dve_config.decode_pool_size;
+            let evict_set = self.eviction_set(needed_evictions, &next_need_set);
+            debug_assert!(evict_set.len() == needed_evictions);
+            for frame_ts in evict_set {
+                debug_assert!(!next_need_set.contains(&frame_ts));
+                self.members.remove(&frame_ts);
+            }
+        }
+        self.next_gen += 1;
+        true
+    }
+
+    pub(crate) fn active_gens(&self) -> BTreeSet<usize> {
+        let mut out = BTreeSet::new();
+        for g in self.done_gens_past..self.next_gen {
+            if !self.done_gens_recent.contains(&g) {
+                out.insert(g);
+            }
+        }
+        out
+    }
+
+    pub(crate) fn finish_gen(&mut self, gen: usize) {
+        debug_assert!(self.active_gens().contains(&gen));
+
+        // update the done_gens
+        self.done_gens_recent.insert(gen);
+        loop {
+            match self.done_gens_recent.first() {
+                Some(&first) if first == self.done_gens_past => {
+                    self.done_gens_recent.remove(&first);
+                    self.done_gens_past += 1;
+                }
+                _ => break,
+            }
+        }
+
+        // plan future gens
+        while self.plan_gen() {}
+    }
+
+    pub(crate) fn is_gen_ready(&self, gen: usize) -> bool {
+        debug_assert!(self.active_gens().contains(&gen));
+
+        self.iframes_per_oframe[gen]
+            .iter()
+            .all(|dep_frame| self.members.contains_key(dep_frame))
+    }
+
+    pub(crate) fn get_ready_gen_frames(&self, gen: usize) -> BTreeMap<IFrameRef, Arc<AVFrame>> {
+        debug_assert!(self.is_gen_ready(gen));
+        self.iframes_per_oframe[gen]
+            .iter()
+            .map(|iframeref| (iframeref.clone(), self.members[iframeref].clone()))
+            .collect()
+    }
+
+    pub(crate) fn need_set(&self) -> BTreeSet<&IFrameRef> {
+        let mut out = BTreeSet::new();
+        for gen in self.active_gens() {
+            out.extend(self.iframes_per_oframe[gen].iter());
+        }
+        out
+    }
+}
+
+impl Debug for Pool {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("Pool")
+            .field("done_gens_recent", &self.done_gens_recent)
+            .field("done_gens_past", &self.done_gens_past)
+            .field("next_gen", &self.next_gen)
+            .field("members", &self.members.keys().collect::<Vec<_>>())
+            .field("decoders", &self.decoders.keys().collect::<Vec<_>>())
+            .finish()
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/service.rs.html b/src/vidformer/service.rs.html new file mode 100644 index 0000000..8c5ba64 --- /dev/null +++ b/src/vidformer/service.rs.html @@ -0,0 +1,155 @@ +service.rs - source

vidformer/
service.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
//! Services provide access to media storage.
+
+use std::str::FromStr;
+
+#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
+pub struct Service {
+    pub(crate) service: String,
+    pub(crate) config: std::collections::HashMap<String, String>,
+}
+
+impl Service {
+    pub fn new(service: String, config: std::collections::HashMap<String, String>) -> Self {
+        Service { service, config }
+    }
+}
+
+impl Default for Service {
+    fn default() -> Self {
+        let working_dir = std::env::current_dir()
+            .unwrap()
+            .to_str()
+            .unwrap()
+            .to_string();
+        let mut map = std::collections::HashMap::new();
+        map.insert("root".to_string(), working_dir);
+
+        Service {
+            service: "fs".to_string(),
+            config: map,
+        }
+    }
+}
+
+impl Service {
+    pub(crate) fn operator(&self) -> Result<opendal::Operator, crate::Error> {
+        let op = {
+            let scheme = match opendal::Scheme::from_str(&self.service) {
+                Ok(scheme) => scheme,
+                Err(_) => {
+                    return Err(crate::Error::AVError(format!(
+                        "unsupported service `{}`",
+                        self.service
+                    )));
+                }
+            };
+            let map = self.config.clone();
+            match opendal::Operator::via_iter(scheme, map) {
+                Ok(op) => op,
+                Err(_) => {
+                    return Err(crate::Error::AVError(format!(
+                        "failed to instantiate service {} with config {:?}",
+                        self.service, self.config
+                    )));
+                }
+            }
+        };
+
+        Ok(op)
+    }
+
+    pub(crate) fn blocking_operator(
+        &self,
+        io_runtime: &tokio::runtime::Handle,
+    ) -> Result<opendal::BlockingOperator, crate::Error> {
+        let op = self.operator()?;
+
+        let bop = if op.info().full_capability().blocking {
+            op.blocking()
+        } else {
+            let _x = io_runtime.enter();
+            op.layer(opendal::layers::BlockingLayer::create().unwrap())
+                .blocking()
+        };
+
+        Ok(bop)
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/sir.rs.html b/src/vidformer/sir.rs.html new file mode 100644 index 0000000..e808d82 --- /dev/null +++ b/src/vidformer/sir.rs.html @@ -0,0 +1,443 @@ +sir.rs - source

vidformer/
sir.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
//! Spec Intermediate Representation
+//!
+//! The SIR is a high-level representation of constructing a video frame from source frames and data.
+//! This is the primary interface between specs and the rest of the system.
+
+use crate::dve::Range;
+use num_rational::Rational64;
+use std::collections::BTreeMap;
+use std::collections::BTreeSet;
+use std::fmt;
+use std::fmt::Display;
+use std::fmt::Formatter;
+
+#[derive(Ord, PartialOrd, PartialEq, Eq, Debug, serde::Deserialize, serde::Serialize, Clone)]
+pub enum IndexConst {
+    ILoc(usize),
+    T(Rational64),
+}
+
+#[derive(Ord, PartialOrd, PartialEq, Eq, Debug, serde::Deserialize, serde::Serialize, Clone)]
+pub struct FrameSource {
+    pub(crate) video: String,
+    pub(crate) index: IndexConst,
+}
+
+impl FrameSource {
+    pub fn new(video: String, index: IndexConst) -> Self {
+        FrameSource { video, index }
+    }
+
+    pub fn video(&self) -> &str {
+        &self.video
+    }
+
+    pub fn index(&self) -> &IndexConst {
+        &self.index
+    }
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
+pub struct FilterExpr {
+    pub name: String,
+    pub args: Vec<Expr>,
+    pub kwargs: BTreeMap<String, Expr>,
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
+pub enum Expr {
+    Frame(FrameExpr),
+    Data(DataExpr),
+}
+
+impl Display for Expr {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        match self {
+            Expr::Frame(frame) => write!(f, "{}", frame),
+            Expr::Data(data) => write!(f, "{}", data),
+        }
+    }
+}
+
+impl Expr {
+    pub(crate) fn add_deps<'a>(&'a self, deps: &mut BTreeSet<&'a FrameSource>) {
+        match self {
+            Expr::Frame(frame) => {
+                frame.add_deps(deps);
+            }
+            Expr::Data(_) => {}
+        }
+    }
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
+
+pub enum DataExpr {
+    Bool(bool),
+    Int(i64),
+    String(String),
+    Bytes(Vec<u8>),
+    ArrayRef(String, IndexConst),
+    Float(f64),
+    List(Vec<DataExpr>),
+}
+
+impl Display for DataExpr {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        match self {
+            DataExpr::Bool(b) => write!(f, "{}", b),
+            DataExpr::Int(i) => write!(f, "{}", i),
+            DataExpr::String(s) => write!(f, "\"{}\"", s),
+            DataExpr::Bytes(b) => write!(f, "<{} bytes>", b.len()),
+            DataExpr::Float(n) => write!(f, "{}", n),
+            DataExpr::ArrayRef(name, IndexConst::ILoc(i)) => write!(f, "{}.iloc[{}]", name, i),
+            DataExpr::ArrayRef(name, IndexConst::T(t)) => write!(f, "{}[{}]", name, t),
+            DataExpr::List(list) => {
+                write!(f, "[")?;
+                for (idx, item) in list.iter().enumerate() {
+                    write!(f, "{}", item)?;
+                    if idx < list.len() - 1 {
+                        write!(f, ", ")?;
+                    }
+                }
+                write!(f, "]")
+            }
+        }
+    }
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
+pub enum FrameExpr {
+    Source(FrameSource),
+    Filter(FilterExpr),
+}
+
+impl Display for FrameExpr {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        match self {
+            FrameExpr::Source(src) => {
+                write!(f, "{}{}", src.video, src.index)
+            }
+            FrameExpr::Filter(filter) => {
+                write!(f, "{}(", filter.name)?;
+                for arg in &filter.args {
+                    write!(f, "{}, ", arg)?;
+                }
+                for (k, v) in &filter.kwargs {
+                    write!(f, "{}={}, ", k, v)?;
+                }
+                write!(f, ")")
+            }
+        }
+    }
+}
+
+impl Display for IndexConst {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        match self {
+            IndexConst::ILoc(i) => write!(f, ".iloc[{}]", i),
+            IndexConst::T(t) => write!(f, "[{}]", t),
+        }
+    }
+}
+
+impl FrameExpr {
+    pub(crate) fn add_deps<'a>(&'a self, deps: &mut BTreeSet<&'a FrameSource>) {
+        match self {
+            FrameExpr::Source(src) => {
+                deps.insert(src);
+            }
+            FrameExpr::Filter(filter) => {
+                for arg in &filter.args {
+                    arg.add_deps(deps);
+                }
+                for arg in filter.kwargs.values() {
+                    arg.add_deps(deps);
+                }
+            }
+        }
+    }
+}
+
+pub(crate) struct ProcessSpan {
+    pub(crate) ts: Vec<Rational64>,
+    pub(crate) frames: Vec<FrameExpr>,
+    pub(crate) output_ts_offset: Option<Rational64>,
+}
+
+pub(crate) fn spec_domain(
+    spec: &dyn crate::spec::Spec,
+    context: &crate::dve::Context,
+) -> Vec<Rational64> {
+    spec.domain(&context.spec_ctx())
+}
+
+impl ProcessSpan {
+    pub(crate) fn create(
+        spec: &dyn crate::spec::Spec,
+        context: &crate::dve::Context,
+        range: &Option<Range>,
+    ) -> Self {
+        let spec_ctx = context.spec_ctx();
+
+        let mut ts = spec.domain(&spec_ctx);
+        ts.sort();
+        let ts = ts;
+
+        let mut range_start_ts = None;
+        let ts = match range {
+            Some(range_config) => {
+                assert!(ts.binary_search(&range_config.start).is_ok());
+                assert!(ts.binary_search(&range_config.end).is_ok());
+                if matches!(
+                    range_config.ts_format,
+                    crate::dve::RangeTsFormat::SegmentLocal
+                ) {
+                    range_start_ts = Some(range_config.start);
+                }
+                ts.into_iter()
+                    .filter(|t: &num_rational::Ratio<i64>| {
+                        t >= &range_config.start && t <= &range_config.end
+                    })
+                    .collect()
+            }
+            None => ts,
+        };
+
+        // TODO: parallelize?
+        let mut frames = Vec::with_capacity(ts.len());
+        for t in &ts {
+            frames.push(spec.render(&spec_ctx, t));
+        }
+
+        // TODO: Data-dependent optimizations somewhere here?
+
+        ProcessSpan {
+            ts,
+            frames,
+            output_ts_offset: range_start_ts,
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/source.rs.html b/src/vidformer/source.rs.html new file mode 100644 index 0000000..2ccfa51 --- /dev/null +++ b/src/vidformer/source.rs.html @@ -0,0 +1,571 @@ +source.rs - source

vidformer/
source.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
use log::*;
+use num_rational::Rational64;
+use rusty_ffmpeg::ffi;
+use serde::{Deserialize, Serialize};
+use std::collections::BTreeSet;
+use std::ffi::CStr;
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct SourceFileMeta {
+    streams: Vec<SourceVideoStreamMeta>,
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+pub struct SourceVideoStreamMeta {
+    pub name: String,
+    pub file_path: String,
+    pub stream_idx: usize,
+    pub service: crate::service::Service,
+    pub file_size: u64,
+    pub resolution: (usize, usize),
+    pub codec: String,
+    pub pix_fmt: String,
+    pub ts: Vec<Rational64>,
+    pub keys: Vec<Rational64>,
+}
+
+pub fn create_profile_file(streams: &[SourceVideoStreamMeta]) -> SourceFileMeta {
+    let streams = streams.to_vec();
+    SourceFileMeta { streams }
+}
+
+impl SourceVideoStreamMeta {
+    pub fn profile(
+        source_name: &str,
+        vid_path: &str,
+        stream: usize,
+        service: &crate::service::Service,
+    ) -> Result<Self, crate::dve::Error> {
+        let io_runtime = tokio::runtime::Builder::new_multi_thread()
+            .worker_threads(1)
+            .enable_all()
+            .build()
+            .unwrap();
+
+        let file_size = {
+            let op = service.blocking_operator(io_runtime.handle())?;
+            let file_stat = op.stat(vid_path);
+
+            let file_stat = match file_stat {
+                Ok(stat) => stat,
+                Err(e) if e.kind() == opendal::ErrorKind::NotFound => {
+                    return Err(crate::dve::Error::IOError(format!(
+                        "File `{}` not found",
+                        vid_path
+                    )));
+                }
+                Err(e) => {
+                    return Err(crate::dve::Error::AVError(format!(
+                        "Failed to stat file {}: {}",
+                        vid_path, e
+                    )));
+                }
+            };
+
+            assert!(file_stat.is_file());
+            file_stat.content_length()
+        };
+
+        let mut demuxer = crate::av::demuxer::Demuxer::new(
+            vid_path,
+            stream,
+            service,
+            file_size,
+            io_runtime.handle(),
+        )?;
+
+        let codec_name = unsafe {
+            CStr::from_ptr(ffi::avcodec_get_name(
+                (*((*demuxer.stream).codecpar)).codec_id,
+            ))
+            .to_str()
+            .unwrap()
+            .to_string()
+        };
+
+        let resolution = unsafe {
+            (
+                (*((*demuxer.stream).codecpar)).width as usize,
+                (*((*demuxer.stream).codecpar)).height as usize,
+            )
+        };
+
+        let time_base = crate::util::avrat_to_rat(unsafe { &(*demuxer.stream).time_base });
+
+        let pix_fmt = unsafe { (*((*demuxer.stream).codecpar)).format };
+        let pix_fmt_name = unsafe {
+            CStr::from_ptr(ffi::av_get_pix_fmt_name(pix_fmt))
+                .to_str()
+                .unwrap()
+                .to_string()
+        };
+
+        let packet = unsafe { ffi::av_packet_alloc().as_mut() }
+            .expect("failed to allocated memory for AVPacket");
+
+        let mut pts_array = Vec::new();
+        let mut key_array = Vec::new();
+
+        while demuxer.read_packet(packet).is_some() {
+            debug_assert!(packet.flags as u32 & ffi::AV_PKT_FLAG_CORRUPT == 0);
+            trace!(
+                "AVPacket [pts {}, dts {}, duration {}, stream {}, key={}]",
+                packet.pts,
+                packet.dts,
+                packet.duration,
+                packet.stream_index,
+                packet.flags as u32 & ffi::AV_PKT_FLAG_KEY != 0
+            );
+
+            // make sure the first frame is a keyframe
+            if pts_array.is_empty() && packet.flags as u32 & ffi::AV_PKT_FLAG_KEY == 0 {
+                return Err(crate::dve::Error::AVError(
+                    "First frame is not a keyframe".to_string(),
+                ));
+            }
+
+            // make sure a keyframe is always the new max pts
+            if packet.flags as u32 & ffi::AV_PKT_FLAG_KEY != 0
+                && !pts_array.is_empty()
+                && packet.pts <= pts_array[pts_array.len() - 1]
+            {
+                return Err(crate::dve::Error::AVError(format!(
+                    "Keyframe pts {} is not past the most recent frame {}",
+                    packet.pts,
+                    pts_array[pts_array.len() - 1]
+                )));
+            }
+
+            // make sure a non-keyframe is always past the most recent keyframe
+            if packet.flags as u32 & ffi::AV_PKT_FLAG_KEY == 0
+                && !key_array.is_empty()
+                && packet.pts <= key_array[key_array.len() - 1]
+            {
+                return Err(crate::dve::Error::AVError(format!(
+                    "Non-keyframe pts {} is not past the most recent keyframe {}",
+                    packet.pts,
+                    key_array[key_array.len() - 1]
+                )));
+            }
+
+            match pts_array.binary_search(&packet.pts) {
+                Ok(_) => {
+                    return Err(crate::dve::Error::AVError(format!(
+                        "Duplicate pts {}",
+                        packet.pts
+                    )));
+                }
+                Err(idx) => {
+                    pts_array.insert(idx, packet.pts);
+                }
+            }
+            if packet.flags as u32 & ffi::AV_PKT_FLAG_KEY != 0 {
+                assert!(key_array.is_empty() || key_array[key_array.len() - 1] < packet.pts); // keyframes should always go in order
+                key_array.push(packet.pts);
+            }
+
+            unsafe { ffi::av_packet_unref(packet) };
+        }
+
+        unsafe {
+            ffi::av_packet_free(&mut (packet as *mut _));
+        }
+        demuxer.close();
+
+        let pts_array = pts_array
+            .iter()
+            .map(|&x| Rational64::new(x, 1) * time_base)
+            .collect();
+
+        let key_array: Vec<Rational64> = key_array
+            .iter()
+            .map(|&x| Rational64::new(x, 1) * time_base)
+            .collect();
+
+        Ok(SourceVideoStreamMeta {
+            name: source_name.to_string(),
+            codec: codec_name,
+            stream_idx: stream,
+            service: service.clone(),
+            file_size,
+            resolution,
+            pix_fmt: pix_fmt_name,
+            ts: pts_array,
+            keys: key_array,
+            file_path: vid_path.to_string(),
+        })
+    }
+
+    pub fn validate(
+        source_name: &str,
+        vid_path: &str,
+        stream: usize,
+        service: &crate::service::Service,
+    ) {
+        let io_runtime = tokio::runtime::Builder::new_multi_thread()
+            .worker_threads(1)
+            .enable_all()
+            .build()
+            .unwrap();
+
+        // First profile
+        let source_profile =
+            SourceVideoStreamMeta::profile(source_name, vid_path, stream, service).unwrap();
+
+        // Do a full decode
+        {
+            let mut decoded_frames = 0;
+            let mut framesource = crate::av::framesource::FrameSource::new(
+                vid_path,
+                stream,
+                &0.into(),
+                service,
+                source_profile.file_size,
+                io_runtime.handle(),
+            )
+            .unwrap();
+            while framesource.next_frame().unwrap().is_some() {
+                decoded_frames += 1;
+            }
+            assert_eq!(decoded_frames, source_profile.ts.len());
+        }
+
+        // Decode each GOP individually, check we see expected behavior
+        {
+            let mut decoded_frames = 0;
+            for (i, key) in source_profile.keys.iter().enumerate() {
+                let mut framesource = crate::av::framesource::FrameSource::new(
+                    vid_path,
+                    stream,
+                    key,
+                    service,
+                    source_profile.file_size,
+                    io_runtime.handle(),
+                )
+                .unwrap();
+
+                let mut expected_frame_ts: BTreeSet<&Rational64> =
+                    source_profile.gop_times(i).iter().collect();
+                let mut first_frame = true;
+
+                while framesource.next_frame().unwrap().is_some() {
+                    decoded_frames += 1;
+                    let ts = Rational64::new(unsafe { (*framesource.frame).pts }, 1)
+                        * framesource.time_base();
+
+                    if first_frame {
+                        assert_eq!(ts, *key);
+                        first_frame = false;
+                    }
+
+                    assert!(expected_frame_ts.remove(&ts));
+                    if expected_frame_ts.is_empty() {
+                        break;
+                    }
+                }
+
+                assert!(expected_frame_ts.is_empty());
+            }
+
+            assert_eq!(decoded_frames, source_profile.ts.len());
+        }
+    }
+
+    fn gop_times(&self, gop: usize) -> &[Rational64] {
+        debug_assert!(gop < self.keys.len());
+        let start_i = self.ts.binary_search(&self.keys[gop]).unwrap();
+        let end_i = if gop == self.keys.len() - 1 {
+            self.ts.len()
+        } else {
+            self.ts.binary_search(&self.keys[gop + 1]).unwrap()
+        };
+
+        &self.ts[start_i..end_i]
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/spec.rs.html b/src/vidformer/spec.rs.html new file mode 100644 index 0000000..6d1d4ae --- /dev/null +++ b/src/vidformer/spec.rs.html @@ -0,0 +1,153 @@ +spec.rs - source

vidformer/
spec.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
//! Specs declarativly define an edited video.
+//!
+//! A spec defines an output video (as a logical time-indexed array).
+//! It creates this array by defining its domain (the set of times at which the spec is defined) and a function that maps each time to a frame.
+//! The frame is represented as an [`FrameExpr`] expression.
+//!
+//! Specs are stateless and immutable. They are intended to be smaller than just storing the entire output video as an array.
+//! Additionally, this generic spec interface allows the general case of a video-editing DSL, as done in V2V, while allowing for whatever language the use case needs.
+
+use crate::sir::FrameExpr;
+use num_rational::Rational64;
+
+/// A trait for providing information to a spec during runtime
+pub trait SpecContext {}
+
+/// A trait for a spec
+///
+/// A spec defines a video from a sequence of transformations.
+/// A [`SpecContext`] is provided for information about the available source videos and arrays.
+pub trait Spec: Sync + Send {
+    /// Returns the domain of the spec.
+    ///
+    /// The domain is the set of times at which the spec is defined.
+    /// Each time corresponds to a single output frame at that timestamp.
+    ///
+    /// The output must:
+    /// - Be sorted in ascending order
+    /// - Contain no duplicate values
+    /// - Begin with 0
+    fn domain(&self, context: &dyn SpecContext) -> Vec<Rational64>;
+
+    /// Returns the "logically" rendered frame at a given time.
+    ///
+    /// This function should assume that the time is in the domain of the spec.
+    fn render(&self, context: &dyn SpecContext, t: &Rational64) -> FrameExpr;
+}
+
+pub(crate) fn get_framerate(spec: &dyn Spec) -> usize {
+    // TODO: Not all framerates are widely supported in HLS. We should probably add a check for that.
+
+    let context = crate::dve::EmptySpecCtx;
+    let frame_times = spec.domain(&context);
+
+    let mut frame_deltas = frame_times.windows(2).map(|w| w[1] - w[0]);
+
+    // Default to 30fps if there's only one frame. Not ideal, but framerate doesn't matter in that case.
+    // We don't want a user to try one frame and it break on them.
+    // TODO: Error on this case?
+    let first_delta = frame_deltas.next().unwrap_or(Rational64::new(1, 30));
+
+    assert!(frame_deltas.all(|d| d == first_delta));
+    assert_eq!(*first_delta.numer(), 1, "Frame rate must be an integer");
+
+    *first_delta.denom() as usize
+}
+
+/// A spec backed by a JSON file
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct JsonSpec {
+    pub frames: Vec<(Rational64, FrameExpr)>,
+}
+
+impl Spec for JsonSpec {
+    fn domain(&self, _context: &dyn SpecContext) -> Vec<Rational64> {
+        self.frames.iter().map(|(t, _)| *t).collect()
+    }
+
+    fn render(&self, _context: &dyn SpecContext, t: &Rational64) -> FrameExpr {
+        let index = self
+            .frames
+            .binary_search_by(|(t2, _)| t2.partial_cmp(t).unwrap())
+            .unwrap();
+
+        self.frames[index].1.clone()
+    }
+}
+
\ No newline at end of file diff --git a/src/vidformer/util.rs.html b/src/vidformer/util.rs.html new file mode 100644 index 0000000..1569583 --- /dev/null +++ b/src/vidformer/util.rs.html @@ -0,0 +1,229 @@ +util.rs - source

vidformer/
util.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
use num_rational::Rational64;
+use rusty_ffmpeg::ffi;
+use std::ffi::CStr;
+use std::ffi::CString;
+
+pub(crate) fn avrat_to_rat(avr: &ffi::AVRational) -> Rational64 {
+    Rational64::new(avr.num as i64, avr.den as i64)
+}
+
+pub(crate) fn rat_to_avrat(rat: &Rational64) -> ffi::AVRational {
+    ffi::AVRational {
+        num: *rat.numer() as i32,
+        den: *rat.denom() as i32,
+    }
+}
+
+pub fn rand_uuid() -> String {
+    uuid::Uuid::new_v4().to_string()
+}
+
+/// Instantiate FFmpeg logging
+pub fn init() {
+    unsafe {
+        // TODO: Should be WARNING, but it keeps throwing sws warnings
+        ffi::av_log_set_level(ffi::AV_LOG_ERROR as i32);
+    }
+}
+
+#[derive(Debug)]
+pub struct CodecDescriptor {
+    pub name: String,
+    pub long_name: String,
+    pub format_id_pretty_name: String,
+    pub has_decoder: bool,
+    pub has_encoder: bool,
+}
+
+/// List all available codecs
+pub fn codecs() -> Vec<CodecDescriptor> {
+    let mut out = Vec::new();
+    unsafe {
+        let mut codec: *const ffi::AVCodecDescriptor = std::ptr::null();
+        while {
+            codec = ffi::avcodec_descriptor_next(codec);
+            !codec.is_null()
+        } {
+            let codec = &*codec;
+            if codec.type_ != ffi::AVMediaType_AVMEDIA_TYPE_VIDEO {
+                continue;
+            }
+
+            let name = CString::new(CStr::from_ptr(codec.name).to_bytes()).unwrap();
+            let long_name = CString::new(CStr::from_ptr(codec.long_name).to_bytes()).unwrap();
+            let id = codec.id;
+            let format_id_pretty_name = ffi::avcodec_get_name(id);
+            let format_id_pretty_name =
+                CString::new(CStr::from_ptr(format_id_pretty_name).to_bytes()).unwrap();
+
+            let has_decoder = !ffi::avcodec_find_decoder(id).is_null();
+            let has_encoder = !ffi::avcodec_find_encoder(id).is_null();
+
+            out.push(CodecDescriptor {
+                name: name.to_str().unwrap().to_string(),
+                long_name: long_name.to_str().unwrap().to_string(),
+                format_id_pretty_name: format_id_pretty_name.to_str().unwrap().to_string(),
+                has_decoder,
+                has_encoder,
+            });
+        }
+    }
+
+    out
+}
+
+pub(crate) fn fmt_av_codec(format: &ffi::AVCodec) -> String {
+    let name = CString::new(unsafe { CStr::from_ptr(format.name) }.to_bytes()).unwrap();
+    let long_name = CString::new(unsafe { CStr::from_ptr(format.long_name) }.to_bytes()).unwrap();
+    let id = format.id;
+    let format_id_pretty_name = unsafe {
+        let format_id_pretty_name = ffi::avcodec_get_name(id);
+        CString::new(CStr::from_ptr(format_id_pretty_name).to_bytes()).unwrap()
+    };
+    format!(
+        "{}/{}/{}",
+        name.to_str().unwrap(),
+        long_name.to_str().unwrap(),
+        format_id_pretty_name.to_str().unwrap()
+    )
+}
+
+pub(crate) fn pixel_fmt_str_to_av_pix_fmt(s: &str) -> Result<ffi::AVPixelFormat, String> {
+    let s = CString::new(s).unwrap();
+    let fmt = unsafe { ffi::av_get_pix_fmt(s.as_ptr()) };
+    if fmt == ffi::AVPixelFormat_AV_PIX_FMT_NONE {
+        Err(format!("Invalid pixel format: {}", s.to_str().unwrap()))
+    } else {
+        Ok(fmt)
+    }
+}
+
+pub(crate) fn pixel_fmt_str(n: i32) -> &'static str {
+    unsafe {
+        let fmt = ffi::av_get_pix_fmt_name(n);
+        CStr::from_ptr(fmt).to_str().unwrap()
+    }
+}
+
+pub(crate) fn av_strerror(err: i32) -> String {
+    let mut buf = [0u8; 1024];
+    unsafe {
+        ffi::av_strerror(err, buf.as_mut_ptr() as *mut _, buf.len());
+    }
+    String::from_utf8_lossy(&buf).to_string()
+}
+
\ No newline at end of file diff --git a/static.files/COPYRIGHT-23e9bde6c69aea69.txt b/static.files/COPYRIGHT-23e9bde6c69aea69.txt new file mode 100644 index 0000000..1447df7 --- /dev/null +++ b/static.files/COPYRIGHT-23e9bde6c69aea69.txt @@ -0,0 +1,50 @@ +# REUSE-IgnoreStart + +These documentation pages include resources by third parties. This copyright +file applies only to those resources. The following third party resources are +included, and carry their own copyright notices and license terms: + +* Fira Sans (FiraSans-Regular.woff2, FiraSans-Medium.woff2): + + Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ + with Reserved Font Name Fira Sans. + + Copyright (c) 2014, Telefonica S.A. + + Licensed under the SIL Open Font License, Version 1.1. + See FiraSans-LICENSE.txt. + +* rustdoc.css, main.js, and playpen.js: + + Copyright 2015 The Rust Developers. + Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or + the MIT license (LICENSE-MIT.txt) at your option. + +* normalize.css: + + Copyright (c) Nicolas Gallagher and Jonathan Neal. + Licensed under the MIT license (see LICENSE-MIT.txt). + +* Source Code Pro (SourceCodePro-Regular.ttf.woff2, + SourceCodePro-Semibold.ttf.woff2, SourceCodePro-It.ttf.woff2): + + Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark + of Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceCodePro-LICENSE.txt. + +* Source Serif 4 (SourceSerif4-Regular.ttf.woff2, SourceSerif4-Bold.ttf.woff2, + SourceSerif4-It.ttf.woff2): + + Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name + 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United + States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceSerif4-LICENSE.md. + +This copyright file is intended to be distributed with rustdoc output. + +# REUSE-IgnoreEnd diff --git a/static.files/FiraSans-LICENSE-db4b642586e02d97.txt b/static.files/FiraSans-LICENSE-db4b642586e02d97.txt new file mode 100644 index 0000000..d7e9c14 --- /dev/null +++ b/static.files/FiraSans-LICENSE-db4b642586e02d97.txt @@ -0,0 +1,98 @@ +// REUSE-IgnoreStart + +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +with Reserved Font Name < Fira >, + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/FiraSans-Medium-8f9a781e4970d388.woff2 b/static.files/FiraSans-Medium-8f9a781e4970d388.woff2 new file mode 100644 index 0000000..7a1e5fc Binary files /dev/null and b/static.files/FiraSans-Medium-8f9a781e4970d388.woff2 differ diff --git a/static.files/FiraSans-Regular-018c141bf0843ffd.woff2 b/static.files/FiraSans-Regular-018c141bf0843ffd.woff2 new file mode 100644 index 0000000..e766e06 Binary files /dev/null and b/static.files/FiraSans-Regular-018c141bf0843ffd.woff2 differ diff --git a/static.files/LICENSE-APACHE-b91fa81cba47b86a.txt b/static.files/LICENSE-APACHE-b91fa81cba47b86a.txt new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/static.files/LICENSE-APACHE-b91fa81cba47b86a.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/static.files/LICENSE-MIT-65090b722b3f6c56.txt b/static.files/LICENSE-MIT-65090b722b3f6c56.txt new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/static.files/LICENSE-MIT-65090b722b3f6c56.txt @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/static.files/NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2 b/static.files/NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2 new file mode 100644 index 0000000..1866ad4 Binary files /dev/null and b/static.files/NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2 differ diff --git a/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt b/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt new file mode 100644 index 0000000..4b3edc2 --- /dev/null +++ b/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt @@ -0,0 +1,103 @@ +// REUSE-IgnoreStart + +Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/), + +with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, +NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, +Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, +NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, +Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 b/static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 new file mode 100644 index 0000000..462c34e Binary files /dev/null and b/static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 differ diff --git a/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt b/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt new file mode 100644 index 0000000..0d2941e --- /dev/null +++ b/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt @@ -0,0 +1,97 @@ +// REUSE-IgnoreStart + +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 b/static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 new file mode 100644 index 0000000..10b558e Binary files /dev/null and b/static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 differ diff --git a/static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2 b/static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2 new file mode 100644 index 0000000..5ec64ee Binary files /dev/null and b/static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2 differ diff --git a/static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 b/static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 new file mode 100644 index 0000000..181a07f Binary files /dev/null and b/static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 differ diff --git a/static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 b/static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 new file mode 100644 index 0000000..2ae08a7 Binary files /dev/null and b/static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 differ diff --git a/static.files/SourceSerif4-LICENSE-3bb119e13b1258b7.md b/static.files/SourceSerif4-LICENSE-3bb119e13b1258b7.md new file mode 100644 index 0000000..175fa4f --- /dev/null +++ b/static.files/SourceSerif4-LICENSE-3bb119e13b1258b7.md @@ -0,0 +1,98 @@ + + +Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. +Copyright 2014 - 2023 Adobe (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + + diff --git a/static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 b/static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 new file mode 100644 index 0000000..0263fc3 Binary files /dev/null and b/static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 differ diff --git a/static.files/favicon-2c020d218678b618.svg b/static.files/favicon-2c020d218678b618.svg new file mode 100644 index 0000000..8b34b51 --- /dev/null +++ b/static.files/favicon-2c020d218678b618.svg @@ -0,0 +1,24 @@ + + + + + diff --git a/static.files/favicon-32x32-422f7d1d52889060.png b/static.files/favicon-32x32-422f7d1d52889060.png new file mode 100644 index 0000000..69b8613 Binary files /dev/null and b/static.files/favicon-32x32-422f7d1d52889060.png differ diff --git a/static.files/main-f070b9041d14864c.js b/static.files/main-f070b9041d14864c.js new file mode 100644 index 0000000..3d672cb --- /dev/null +++ b/static.files/main-f070b9041d14864c.js @@ -0,0 +1,11 @@ +"use strict";window.RUSTDOC_TOOLTIP_HOVER_MS=300;window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS=450;function resourcePath(basename,extension){return getVar("root-path")+basename+getVar("resource-suffix")+extension}function hideMain(){addClass(document.getElementById(MAIN_ID),"hidden");const toggle=document.getElementById("toggle-all-docs");if(toggle){toggle.setAttribute("disabled","disabled")}}function showMain(){const main=document.getElementById(MAIN_ID);removeClass(main,"hidden");const mainHeading=main.querySelector(".main-heading");if(mainHeading&&searchState.rustdocToolbar){if(searchState.rustdocToolbar.parentElement){searchState.rustdocToolbar.parentElement.removeChild(searchState.rustdocToolbar)}mainHeading.appendChild(searchState.rustdocToolbar)}const toggle=document.getElementById("toggle-all-docs");if(toggle){toggle.removeAttribute("disabled")}}window.rootPath=getVar("root-path");window.currentCrate=getVar("current-crate");function setMobileTopbar(){const mobileTopbar=document.querySelector(".mobile-topbar");const locationTitle=document.querySelector(".sidebar h2.location");if(mobileTopbar){const mobileTitle=document.createElement("h2");mobileTitle.className="location";if(hasClass(document.querySelector(".rustdoc"),"crate")){mobileTitle.innerHTML=`Crate ${window.currentCrate}`}else if(locationTitle){mobileTitle.innerHTML=locationTitle.innerHTML}mobileTopbar.appendChild(mobileTitle)}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!=="undefined"){return ev.key}const c=ev.charCode||ev.keyCode;if(c===27){return"Escape"}return String.fromCharCode(c)}const MAIN_ID="main-content";const SETTINGS_BUTTON_ID="settings-menu";const ALTERNATIVE_DISPLAY_ID="alternative-display";const NOT_DISPLAYED_ID="not-displayed";const HELP_BUTTON_ID="help-button";function getSettingsButton(){return document.getElementById(SETTINGS_BUTTON_ID)}function getHelpButton(){return document.getElementById(HELP_BUTTON_ID)}function getNakedUrl(){return window.location.href.split("?")[0].split("#")[0]}function insertAfter(newNode,referenceNode){referenceNode.parentNode.insertBefore(newNode,referenceNode.nextSibling)}function getOrCreateSection(id,classes){let el=document.getElementById(id);if(!el){el=document.createElement("section");el.id=id;el.className=classes;insertAfter(el,document.getElementById(MAIN_ID))}return el}function getAlternativeDisplayElem(){return getOrCreateSection(ALTERNATIVE_DISPLAY_ID,"content hidden")}function getNotDisplayedElem(){return getOrCreateSection(NOT_DISPLAYED_ID,"hidden")}function switchDisplayedElement(elemToDisplay){const el=getAlternativeDisplayElem();if(el.children.length>0){getNotDisplayedElem().appendChild(el.firstElementChild)}if(elemToDisplay===null){addClass(el,"hidden");showMain();return}el.appendChild(elemToDisplay);hideMain();removeClass(el,"hidden");const mainHeading=elemToDisplay.querySelector(".main-heading");if(mainHeading&&searchState.rustdocToolbar){if(searchState.rustdocToolbar.parentElement){searchState.rustdocToolbar.parentElement.removeChild(searchState.rustdocToolbar)}mainHeading.appendChild(searchState.rustdocToolbar)}}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function preLoadCss(cssUrl){const link=document.createElement("link");link.href=cssUrl;link.rel="preload";link.as="style";document.getElementsByTagName("head")[0].appendChild(link)}(function(){const isHelpPage=window.location.pathname.endsWith("/help.html");function loadScript(url,errorCallback){const script=document.createElement("script");script.src=url;if(errorCallback!==undefined){script.onerror=errorCallback}document.head.append(script)}if(getSettingsButton()){getSettingsButton().onclick=event=>{if(event.ctrlKey||event.altKey||event.metaKey){return}window.hideAllModals(false);addClass(getSettingsButton(),"rotate");event.preventDefault();loadScript(getVar("static-root-path")+getVar("settings-js"));setTimeout(()=>{const themes=getVar("themes").split(",");for(const theme of themes){if(theme!==""){preLoadCss(getVar("root-path")+theme+".css")}}},0)}}window.searchState={rustdocToolbar:document.querySelector("rustdoc-toolbar"),loadingText:"Loading search results...",input:document.getElementsByClassName("search-input")[0],outputElement:()=>{let el=document.getElementById("search");if(!el){el=document.createElement("section");el.id="search";getNotDisplayedElem().appendChild(el)}return el},title:document.title,titleBeforeSearch:document.title,timeout:null,currentTab:0,focusedByTab:[null,null,null],clearInputTimeout:()=>{if(searchState.timeout!==null){clearTimeout(searchState.timeout);searchState.timeout=null}},isDisplayed:()=>searchState.outputElement().parentElement.id===ALTERNATIVE_DISPLAY_ID,focus:()=>{searchState.input.focus()},defocus:()=>{searchState.input.blur()},showResults:search=>{if(search===null||typeof search==="undefined"){search=searchState.outputElement()}switchDisplayedElement(search);searchState.mouseMovedAfterSearch=false;document.title=searchState.title},removeQueryParameters:()=>{document.title=searchState.titleBeforeSearch;if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.hash)}},hideResults:()=>{switchDisplayedElement(null);searchState.removeQueryParameters()},getQueryStringParams:()=>{const params={};window.location.search.substring(1).split("&").map(s=>{const pair=s.split("=").map(x=>x.replace(/\+/g," "));params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params},setup:()=>{const search_input=searchState.input;if(!searchState.input){return}let searchLoaded=false;function sendSearchForm(){document.getElementsByClassName("search-form")[0].submit()}function loadSearch(){if(!searchLoaded){searchLoaded=true;loadScript(getVar("static-root-path")+getVar("search-js"),sendSearchForm);loadScript(resourcePath("search-index",".js"),sendSearchForm)}}search_input.addEventListener("focus",()=>{search_input.origPlaceholder=search_input.placeholder;search_input.placeholder="Type your search here.";loadSearch()});if(search_input.value!==""){loadSearch()}const params=searchState.getQueryStringParams();if(params.search!==undefined){searchState.setLoadingSearch();loadSearch()}},setLoadingSearch:()=>{const search=searchState.outputElement();search.innerHTML="

"+searchState.loadingText+"

";searchState.showResults(search)},descShards:new Map(),loadDesc:async function({descShard,descIndex}){if(descShard.promise===null){descShard.promise=new Promise((resolve,reject)=>{descShard.resolve=resolve;const ds=descShard;const fname=`${ds.crate}-desc-${ds.shard}-`;const url=resourcePath(`search.desc/${descShard.crate}/${fname}`,".js",);loadScript(url,reject)})}const list=await descShard.promise;return list[descIndex]},loadedDescShard:function(crate,shard,data){this.descShards.get(crate)[shard].resolve(data.split("\n"))},};const toggleAllDocsId="toggle-all-docs";let savedHash="";function handleHashes(ev){if(ev!==null&&searchState.isDisplayed()&&ev.newURL){switchDisplayedElement(null);const hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.search+"#"+hash)}const elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}const pageId=window.location.hash.replace(/^#/,"");if(savedHash!==pageId){savedHash=pageId;if(pageId!==""){expandSection(pageId)}}if(savedHash.startsWith("impl-")){const splitAt=savedHash.indexOf("/");if(splitAt!==-1){const implId=savedHash.slice(0,splitAt);const assocId=savedHash.slice(splitAt+1);const implElems=document.querySelectorAll(`details > summary > section[id^="${implId}"]`,);onEachLazy(implElems,implElem=>{const numbered=/^(.+?)-([0-9]+)$/.exec(implElem.id);if(implElem.id!==implId&&(!numbered||numbered[1]!==implId)){return false}return onEachLazy(implElem.parentElement.parentElement.querySelectorAll(`[id^="${assocId}"]`),item=>{const numbered=/^(.+?)-([0-9]+)$/.exec(item.id);if(item.id===assocId||(numbered&&numbered[1]===assocId)){openParentDetails(item);item.scrollIntoView();setTimeout(()=>{window.location.replace("#"+item.id)},0);return true}},)})}}}function onHashChange(ev){hideSidebar();handleHashes(ev)}function openParentDetails(elem){while(elem){if(elem.tagName==="DETAILS"){elem.open=true}elem=elem.parentNode}}function expandSection(id){openParentDetails(document.getElementById(id))}function handleEscape(ev){searchState.clearInputTimeout();searchState.hideResults();ev.preventDefault();searchState.defocus();window.hideAllModals(true)}function handleShortcut(ev){const disableShortcuts=getSettingValue("disable-shortcuts")==="true";if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts){return}if(document.activeElement.tagName==="INPUT"&&document.activeElement.type!=="checkbox"&&document.activeElement.type!=="radio"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":case"/":ev.preventDefault();searchState.focus();break;case"+":ev.preventDefault();expandAllDocs();break;case"-":ev.preventDefault();collapseAllDocs();break;case"?":showHelp();break;default:break}}}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function addSidebarItems(){if(!window.SIDEBAR_ITEMS){return}const sidebar=document.getElementById("rustdoc-modnav");function block(shortty,id,longty){const filtered=window.SIDEBAR_ITEMS[shortty];if(!filtered){return}const modpath=hasClass(document.querySelector(".rustdoc"),"mod")?"../":"";const h3=document.createElement("h3");h3.innerHTML=`${longty}`;const ul=document.createElement("ul");ul.className="block "+shortty;for(const name of filtered){let path;if(shortty==="mod"){path=`${modpath}${name}/index.html`}else{path=`${modpath}${shortty}.${name}.html`}let current_page=document.location.href.toString();if(current_page.endsWith("/")){current_page+="index.html"}const link=document.createElement("a");link.href=path;link.textContent=name;const li=document.createElement("li");if(link.href===current_page){li.classList.add("current")}li.appendChild(link);ul.appendChild(li)}sidebar.appendChild(h3);sidebar.appendChild(ul)}if(sidebar){block("primitive","primitives","Primitive Types");block("mod","modules","Modules");block("macro","macros","Macros");block("struct","structs","Structs");block("enum","enums","Enums");block("constant","constants","Constants");block("static","static","Statics");block("trait","traits","Traits");block("fn","functions","Functions");block("type","types","Type Aliases");block("union","unions","Unions");block("foreigntype","foreign-types","Foreign Types");block("keyword","keywords","Keywords");block("attr","attributes","Attribute Macros");block("derive","derives","Derive Macros");block("traitalias","trait-aliases","Trait Aliases")}}window.register_implementors=imp=>{const implementors=document.getElementById("implementors-list");const synthetic_implementors=document.getElementById("synthetic-implementors-list");const inlined_types=new Set();const TEXT_IDX=0;const SYNTHETIC_IDX=1;const TYPES_IDX=2;if(synthetic_implementors){onEachLazy(synthetic_implementors.getElementsByClassName("impl"),el=>{const aliases=el.getAttribute("data-aliases");if(!aliases){return}aliases.split(",").forEach(alias=>{inlined_types.add(alias)})})}let currentNbImpls=implementors.getElementsByClassName("impl").length;const traitName=document.querySelector(".main-heading h1 > .trait").textContent;const baseIdName="impl-"+traitName+"-";const libs=Object.getOwnPropertyNames(imp);const script=document.querySelector("script[data-ignore-extern-crates]");const ignoreExternCrates=new Set((script?script.getAttribute("data-ignore-extern-crates"):"").split(","),);for(const lib of libs){if(lib===window.currentCrate||ignoreExternCrates.has(lib)){continue}const structs=imp[lib];struct_loop:for(const struct of structs){const list=struct[SYNTHETIC_IDX]?synthetic_implementors:implementors;if(struct[SYNTHETIC_IDX]){for(const struct_type of struct[TYPES_IDX]){if(inlined_types.has(struct_type)){continue struct_loop}inlined_types.add(struct_type)}}const code=document.createElement("h3");code.innerHTML=struct[TEXT_IDX];addClass(code,"code-header");onEachLazy(code.getElementsByTagName("a"),elem=>{const href=elem.getAttribute("href");if(href&&!href.startsWith("#")&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});const currentId=baseIdName+currentNbImpls;const anchor=document.createElement("a");anchor.href="#"+currentId;addClass(anchor,"anchor");const display=document.createElement("div");display.id=currentId;addClass(display,"impl");display.appendChild(anchor);display.appendChild(code);list.appendChild(display);currentNbImpls+=1}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}window.register_type_impls=imp=>{if(!imp||!imp[window.currentCrate]){return}window.pending_type_impls=null;const idMap=new Map();let implementations=document.getElementById("implementations-list");let trait_implementations=document.getElementById("trait-implementations-list");let trait_implementations_header=document.getElementById("trait-implementations");const script=document.querySelector("script[data-self-path]");const selfPath=script?script.getAttribute("data-self-path"):null;const mainContent=document.querySelector("#main-content");const sidebarSection=document.querySelector(".sidebar section");let methods=document.querySelector(".sidebar .block.method");let associatedTypes=document.querySelector(".sidebar .block.associatedtype");let associatedConstants=document.querySelector(".sidebar .block.associatedconstant");let sidebarTraitList=document.querySelector(".sidebar .block.trait-implementation");for(const impList of imp[window.currentCrate]){const types=impList.slice(2);const text=impList[0];const isTrait=impList[1]!==0;const traitName=impList[1];if(types.indexOf(selfPath)===-1){continue}let outputList=isTrait?trait_implementations:implementations;if(outputList===null){const outputListName=isTrait?"Trait Implementations":"Implementations";const outputListId=isTrait?"trait-implementations-list":"implementations-list";const outputListHeaderId=isTrait?"trait-implementations":"implementations";const outputListHeader=document.createElement("h2");outputListHeader.id=outputListHeaderId;outputListHeader.innerText=outputListName;outputList=document.createElement("div");outputList.id=outputListId;if(isTrait){const link=document.createElement("a");link.href=`#${outputListHeaderId}`;link.innerText="Trait Implementations";const h=document.createElement("h3");h.appendChild(link);trait_implementations=outputList;trait_implementations_header=outputListHeader;sidebarSection.appendChild(h);sidebarTraitList=document.createElement("ul");sidebarTraitList.className="block trait-implementation";sidebarSection.appendChild(sidebarTraitList);mainContent.appendChild(outputListHeader);mainContent.appendChild(outputList)}else{implementations=outputList;if(trait_implementations){mainContent.insertBefore(outputListHeader,trait_implementations_header);mainContent.insertBefore(outputList,trait_implementations_header)}else{const mainContent=document.querySelector("#main-content");mainContent.appendChild(outputListHeader);mainContent.appendChild(outputList)}}}const template=document.createElement("template");template.innerHTML=text;onEachLazy(template.content.querySelectorAll("a"),elem=>{const href=elem.getAttribute("href");if(href&&!href.startsWith("#")&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});onEachLazy(template.content.querySelectorAll("[id]"),el=>{let i=0;if(idMap.has(el.id)){i=idMap.get(el.id)}else if(document.getElementById(el.id)){i=1;while(document.getElementById(`${el.id}-${2 * i}`)){i=2*i}while(document.getElementById(`${el.id}-${i}`)){i+=1}}if(i!==0){const oldHref=`#${el.id}`;const newHref=`#${el.id}-${i}`;el.id=`${el.id}-${i}`;onEachLazy(template.content.querySelectorAll("a[href]"),link=>{if(link.getAttribute("href")===oldHref){link.href=newHref}})}idMap.set(el.id,i+1)});const templateAssocItems=template.content.querySelectorAll("section.tymethod, "+"section.method, section.associatedtype, section.associatedconstant");if(isTrait){const li=document.createElement("li");const a=document.createElement("a");a.href=`#${template.content.querySelector(".impl").id}`;a.textContent=traitName;li.appendChild(a);sidebarTraitList.append(li)}else{onEachLazy(templateAssocItems,item=>{let block=hasClass(item,"associatedtype")?associatedTypes:(hasClass(item,"associatedconstant")?associatedConstants:(methods));if(!block){const blockTitle=hasClass(item,"associatedtype")?"Associated Types":(hasClass(item,"associatedconstant")?"Associated Constants":("Methods"));const blockClass=hasClass(item,"associatedtype")?"associatedtype":(hasClass(item,"associatedconstant")?"associatedconstant":("method"));const blockHeader=document.createElement("h3");const blockLink=document.createElement("a");blockLink.href="#implementations";blockLink.innerText=blockTitle;blockHeader.appendChild(blockLink);block=document.createElement("ul");block.className=`block ${blockClass}`;const insertionReference=methods||sidebarTraitList;if(insertionReference){const insertionReferenceH=insertionReference.previousElementSibling;sidebarSection.insertBefore(blockHeader,insertionReferenceH);sidebarSection.insertBefore(block,insertionReferenceH)}else{sidebarSection.appendChild(blockHeader);sidebarSection.appendChild(block)}if(hasClass(item,"associatedtype")){associatedTypes=block}else if(hasClass(item,"associatedconstant")){associatedConstants=block}else{methods=block}}const li=document.createElement("li");const a=document.createElement("a");a.innerText=item.id.split("-")[0].split(".")[1];a.href=`#${item.id}`;li.appendChild(a);block.appendChild(li)})}outputList.appendChild(template.content)}for(const list of[methods,associatedTypes,associatedConstants,sidebarTraitList]){if(!list){continue}const newChildren=Array.prototype.slice.call(list.children);newChildren.sort((a,b)=>{const aI=a.innerText;const bI=b.innerText;return aIbI?1:0});list.replaceChildren(...newChildren)}};if(window.pending_type_impls){window.register_type_impls(window.pending_type_impls)}function addSidebarCrates(){if(!window.ALL_CRATES){return}const sidebarElems=document.getElementById("rustdoc-modnav");if(!sidebarElems){return}const h3=document.createElement("h3");h3.innerHTML="Crates";const ul=document.createElement("ul");ul.className="block crate";for(const crate of window.ALL_CRATES){const link=document.createElement("a");link.href=window.rootPath+crate+"/index.html";link.textContent=crate;const li=document.createElement("li");if(window.rootPath!=="./"&&crate===window.currentCrate){li.className="current"}li.appendChild(link);ul.appendChild(li)}sidebarElems.appendChild(h3);sidebarElems.appendChild(ul)}function expandAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);removeClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hasClass(e,"type-contents-toggle")&&!hasClass(e,"more-examples-toggle")){e.open=true}});innerToggle.children[0].innerText="Summary"}function collapseAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);addClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(e.parentNode.id!=="implementations-list"||(!hasClass(e,"implementors-toggle")&&!hasClass(e,"type-contents-toggle"))){e.open=false}});innerToggle.children[0].innerText="Show all"}function toggleAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);if(!innerToggle){return}if(hasClass(innerToggle,"will-expand")){expandAllDocs()}else{collapseAllDocs()}}(function(){const toggles=document.getElementById(toggleAllDocsId);if(toggles){toggles.onclick=toggleAllDocs}const hideMethodDocs=getSettingValue("auto-hide-method-docs")==="true";const hideImplementations=getSettingValue("auto-hide-trait-implementations")==="true";const hideLargeItemContents=getSettingValue("auto-hide-large-items")!=="false";function setImplementorsTogglesOpen(id,open){const list=document.getElementById(id);if(list!==null){onEachLazy(list.getElementsByClassName("implementors-toggle"),e=>{e.open=open})}}if(hideImplementations){setImplementorsTogglesOpen("trait-implementations-list",false);setImplementorsTogglesOpen("blanket-implementations-list",false)}onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hideLargeItemContents&&hasClass(e,"type-contents-toggle")){e.open=true}if(hideMethodDocs&&hasClass(e,"method-toggle")){e.open=false}})}());window.rustdoc_add_line_numbers_to_examples=()=>{if(document.querySelector(".rustdoc.src")){return}onEachLazy(document.querySelectorAll(":not(.scraped-example) > .example-wrap > pre:not(.example-line-numbers)",),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");if(line_numbers.length>0){return}const count=x.textContent.split("\n").length;const elems=[];for(let i=0;i{onEachLazy(document.querySelectorAll(".example-wrap > .example-line-numbers"),x=>{x.parentNode.removeChild(x)})};if(getSettingValue("line-numbers")==="true"){window.rustdoc_add_line_numbers_to_examples()}function showSidebar(){window.hideAllModals(false);const sidebar=document.getElementsByClassName("sidebar")[0];addClass(sidebar,"shown")}function hideSidebar(){const sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"shown")}window.addEventListener("resize",()=>{if(window.CURRENT_TOOLTIP_ELEMENT){const base=window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE;const force_visible=base.TOOLTIP_FORCE_VISIBLE;hideTooltip(false);if(force_visible){showTooltip(base);base.TOOLTIP_FORCE_VISIBLE=true}}});const mainElem=document.getElementById(MAIN_ID);if(mainElem){mainElem.addEventListener("click",hideSidebar)}onEachLazy(document.querySelectorAll("a[href^='#']"),el=>{el.addEventListener("click",()=>{expandSection(el.hash.slice(1));hideSidebar()})});onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"),el=>{el.addEventListener("click",e=>{if(e.target.tagName!=="SUMMARY"&&e.target.tagName!=="A"){e.preventDefault()}})});function showTooltip(e){const notable_ty=e.getAttribute("data-notable-ty");if(!window.NOTABLE_TRAITS&¬able_ty){const data=document.getElementById("notable-traits-data");if(data){window.NOTABLE_TRAITS=JSON.parse(data.innerText)}else{throw new Error("showTooltip() called with notable without any notable traits!")}}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE===e){clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);return}window.hideAllModals(false);const wrapper=document.createElement("div");if(notable_ty){wrapper.innerHTML="
"+window.NOTABLE_TRAITS[notable_ty]+"
"}else{if(e.getAttribute("title")!==null){e.setAttribute("data-title",e.getAttribute("title"));e.removeAttribute("title")}if(e.getAttribute("data-title")!==null){const titleContent=document.createElement("div");titleContent.className="content";titleContent.appendChild(document.createTextNode(e.getAttribute("data-title")));wrapper.appendChild(titleContent)}}wrapper.className="tooltip popover";const focusCatcher=document.createElement("div");focusCatcher.setAttribute("tabindex","0");focusCatcher.onfocus=hideTooltip;wrapper.appendChild(focusCatcher);const pos=e.getBoundingClientRect();wrapper.style.top=(pos.top+window.scrollY+pos.height)+"px";wrapper.style.left=0;wrapper.style.right="auto";wrapper.style.visibility="hidden";document.body.appendChild(wrapper);const wrapperPos=wrapper.getBoundingClientRect();const finalPos=pos.left+window.scrollX-wrapperPos.width+24;if(finalPos>0){wrapper.style.left=finalPos+"px"}else{wrapper.style.setProperty("--popover-arrow-offset",(wrapperPos.right-pos.right+4)+"px",)}wrapper.style.visibility="";window.CURRENT_TOOLTIP_ELEMENT=wrapper;window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE=e;clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);wrapper.onpointerenter=ev=>{if(ev.pointerType!=="mouse"){return}clearTooltipHoverTimeout(e)};wrapper.onpointerleave=ev=>{if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&!e.contains(ev.relatedTarget)){setTooltipHoverTimeout(e,false);addClass(wrapper,"fade-out")}}}function setTooltipHoverTimeout(element,show){clearTooltipHoverTimeout(element);if(!show&&!window.CURRENT_TOOLTIP_ELEMENT){return}if(show&&window.CURRENT_TOOLTIP_ELEMENT){return}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE!==element){return}element.TOOLTIP_HOVER_TIMEOUT=setTimeout(()=>{if(show){showTooltip(element)}else if(!element.TOOLTIP_FORCE_VISIBLE){hideTooltip(false)}},show?window.RUSTDOC_TOOLTIP_HOVER_MS:window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS)}function clearTooltipHoverTimeout(element){if(element.TOOLTIP_HOVER_TIMEOUT!==undefined){removeClass(window.CURRENT_TOOLTIP_ELEMENT,"fade-out");clearTimeout(element.TOOLTIP_HOVER_TIMEOUT);delete element.TOOLTIP_HOVER_TIMEOUT}}function tooltipBlurHandler(event){if(window.CURRENT_TOOLTIP_ELEMENT&&!window.CURRENT_TOOLTIP_ELEMENT.contains(document.activeElement)&&!window.CURRENT_TOOLTIP_ELEMENT.contains(event.relatedTarget)&&!window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(document.activeElement)&&!window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(event.relatedTarget)){setTimeout(()=>hideTooltip(false),0)}}function hideTooltip(focus){if(window.CURRENT_TOOLTIP_ELEMENT){if(window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE){if(focus){window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.focus()}window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE=false}document.body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);window.CURRENT_TOOLTIP_ELEMENT=null}}onEachLazy(document.getElementsByClassName("tooltip"),e=>{e.onclick=()=>{e.TOOLTIP_FORCE_VISIBLE=e.TOOLTIP_FORCE_VISIBLE?false:true;if(window.CURRENT_TOOLTIP_ELEMENT&&!e.TOOLTIP_FORCE_VISIBLE){hideTooltip(true)}else{showTooltip(e);window.CURRENT_TOOLTIP_ELEMENT.setAttribute("tabindex","0");window.CURRENT_TOOLTIP_ELEMENT.focus();window.CURRENT_TOOLTIP_ELEMENT.onblur=tooltipBlurHandler}return false};e.onpointerenter=ev=>{if(ev.pointerType!=="mouse"){return}setTooltipHoverTimeout(e,true)};e.onpointermove=ev=>{if(ev.pointerType!=="mouse"){return}setTooltipHoverTimeout(e,true)};e.onpointerleave=ev=>{if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&window.CURRENT_TOOLTIP_ELEMENT&&!window.CURRENT_TOOLTIP_ELEMENT.contains(ev.relatedTarget)){setTooltipHoverTimeout(e,false);addClass(window.CURRENT_TOOLTIP_ELEMENT,"fade-out")}}});const sidebar_menu_toggle=document.getElementsByClassName("sidebar-menu-toggle")[0];if(sidebar_menu_toggle){sidebar_menu_toggle.addEventListener("click",()=>{const sidebar=document.getElementsByClassName("sidebar")[0];if(!hasClass(sidebar,"shown")){showSidebar()}else{hideSidebar()}})}function helpBlurHandler(event){if(!getHelpButton().contains(document.activeElement)&&!getHelpButton().contains(event.relatedTarget)&&!getSettingsButton().contains(document.activeElement)&&!getSettingsButton().contains(event.relatedTarget)){window.hidePopoverMenus()}}function buildHelpMenu(){const book_info=document.createElement("span");const channel=getVar("channel");book_info.className="top";book_info.innerHTML=`You can find more information in \ +the rustdoc book.`;const shortcuts=[["?","Show this help dialog"],["S / /","Focus the search field"],["↑","Move up in search results"],["↓","Move down in search results"],["← / →","Switch result tab (when results focused)"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(x=>"
"+x[0].split(" ").map((y,index)=>((index&1)===0?""+y+"":" "+y+" ")).join("")+"
"+x[1]+"
").join("");const div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";const infos=[`For a full list of all search features, take a look here.`,"Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for functions that accept or return \ + slices and \ + arrays by writing \ + square brackets (e.g., -> [u8] or [] -> Option)","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;const rustdoc_version=document.createElement("span");rustdoc_version.className="bottom";const rustdoc_version_code=document.createElement("code");rustdoc_version_code.innerText="rustdoc "+getVar("rustdoc-version");rustdoc_version.appendChild(rustdoc_version_code);const container=document.createElement("div");if(!isHelpPage){container.className="popover"}container.id="help";container.style.display="none";const side_by_side=document.createElement("div");side_by_side.className="side-by-side";side_by_side.appendChild(div_shortcuts);side_by_side.appendChild(div_infos);container.appendChild(book_info);container.appendChild(side_by_side);container.appendChild(rustdoc_version);if(isHelpPage){const help_section=document.createElement("section");help_section.appendChild(container);document.getElementById("main-content").appendChild(help_section);container.style.display="block"}else{const help_button=getHelpButton();help_button.appendChild(container);container.onblur=helpBlurHandler;help_button.onblur=helpBlurHandler;help_button.children[0].onblur=helpBlurHandler}return container}window.hideAllModals=switchFocus=>{hideSidebar();window.hidePopoverMenus();hideTooltip(switchFocus)};window.hidePopoverMenus=()=>{onEachLazy(document.querySelectorAll("rustdoc-toolbar .popover"),elem=>{elem.style.display="none"});const button=getHelpButton();if(button){removeClass(button,"help-open")}};function getHelpMenu(buildNeeded){let menu=getHelpButton().querySelector(".popover");if(!menu&&buildNeeded){menu=buildHelpMenu()}return menu}function showHelp(){const button=getHelpButton();addClass(button,"help-open");button.querySelector("a").focus();const menu=getHelpMenu(true);if(menu.style.display==="none"){window.hideAllModals();menu.style.display=""}}const helpLink=document.querySelector(`#${HELP_BUTTON_ID} > a`);if(isHelpPage){buildHelpMenu()}else if(helpLink){helpLink.addEventListener("click",event=>{if(!helpLink.contains(helpLink)||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault();const menu=getHelpMenu(true);const shouldShowHelp=menu.style.display==="none";if(shouldShowHelp){showHelp()}else{window.hidePopoverMenus()}})}setMobileTopbar();addSidebarItems();addSidebarCrates();onHashChange(null);window.addEventListener("hashchange",onHashChange);searchState.setup()}());(function(){const SIDEBAR_MIN=100;const SIDEBAR_MAX=500;const RUSTDOC_MOBILE_BREAKPOINT=700;const BODY_MIN=400;const SIDEBAR_VANISH_THRESHOLD=SIDEBAR_MIN/2;const sidebarButton=document.getElementById("sidebar-button");if(sidebarButton){sidebarButton.addEventListener("click",e=>{removeClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","false");if(document.querySelector(".rustdoc.src")){window.rustdocToggleSrcSidebar()}e.preventDefault()})}let currentPointerId=null;let desiredSidebarSize=null;let pendingSidebarResizingFrame=false;const resizer=document.querySelector(".sidebar-resizer");const sidebar=document.querySelector(".sidebar");if(!resizer||!sidebar){return}const isSrcPage=hasClass(document.body,"src");function hideSidebar(){if(isSrcPage){window.rustdocCloseSourceSidebar();updateLocalStorage("src-sidebar-width",null);document.documentElement.style.removeProperty("--src-sidebar-width");sidebar.style.removeProperty("--src-sidebar-width");resizer.style.removeProperty("--src-sidebar-width")}else{addClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","true");updateLocalStorage("desktop-sidebar-width",null);document.documentElement.style.removeProperty("--desktop-sidebar-width");sidebar.style.removeProperty("--desktop-sidebar-width");resizer.style.removeProperty("--desktop-sidebar-width")}}function showSidebar(){if(isSrcPage){window.rustdocShowSourceSidebar()}else{removeClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","false")}}function changeSidebarSize(size){if(isSrcPage){updateLocalStorage("src-sidebar-width",size);sidebar.style.setProperty("--src-sidebar-width",size+"px");resizer.style.setProperty("--src-sidebar-width",size+"px")}else{updateLocalStorage("desktop-sidebar-width",size);sidebar.style.setProperty("--desktop-sidebar-width",size+"px");resizer.style.setProperty("--desktop-sidebar-width",size+"px")}}function isSidebarHidden(){return isSrcPage?!hasClass(document.documentElement,"src-sidebar-expanded"):hasClass(document.documentElement,"hide-sidebar")}function resize(e){if(currentPointerId===null||currentPointerId!==e.pointerId){return}e.preventDefault();const pos=e.clientX-3;if(pos=SIDEBAR_MIN){if(isSidebarHidden()){showSidebar()}const constrainedPos=Math.min(pos,window.innerWidth-BODY_MIN,SIDEBAR_MAX);changeSidebarSize(constrainedPos);desiredSidebarSize=constrainedPos;if(pendingSidebarResizingFrame!==false){clearTimeout(pendingSidebarResizingFrame)}pendingSidebarResizingFrame=setTimeout(()=>{if(currentPointerId===null||pendingSidebarResizingFrame===false){return}pendingSidebarResizingFrame=false;document.documentElement.style.setProperty("--resizing-sidebar-width",desiredSidebarSize+"px",)},100)}}window.addEventListener("resize",()=>{if(window.innerWidth=(window.innerWidth-BODY_MIN)){changeSidebarSize(window.innerWidth-BODY_MIN)}else if(desiredSidebarSize!==null&&desiredSidebarSize>SIDEBAR_MIN){changeSidebarSize(desiredSidebarSize)}});function stopResize(e){if(currentPointerId===null){return}if(e){e.preventDefault()}desiredSidebarSize=sidebar.getBoundingClientRect().width;removeClass(resizer,"active");window.removeEventListener("pointermove",resize,false);window.removeEventListener("pointerup",stopResize,false);removeClass(document.documentElement,"sidebar-resizing");document.documentElement.style.removeProperty("--resizing-sidebar-width");if(resizer.releasePointerCapture){resizer.releasePointerCapture(currentPointerId);currentPointerId=null}}function initResize(e){if(currentPointerId!==null||e.altKey||e.ctrlKey||e.metaKey||e.button!==0){return}if(resizer.setPointerCapture){resizer.setPointerCapture(e.pointerId);if(!resizer.hasPointerCapture(e.pointerId)){resizer.releasePointerCapture(e.pointerId);return}currentPointerId=e.pointerId}window.hideAllModals(false);e.preventDefault();window.addEventListener("pointermove",resize,false);window.addEventListener("pointercancel",stopResize,false);window.addEventListener("pointerup",stopResize,false);addClass(resizer,"active");addClass(document.documentElement,"sidebar-resizing");const pos=e.clientX-sidebar.offsetLeft-3;document.documentElement.style.setProperty("--resizing-sidebar-width",pos+"px");desiredSidebarSize=null}resizer.addEventListener("pointerdown",initResize,false)}());(function(){function copyContentToClipboard(content){const el=document.createElement("textarea");el.value=content;el.setAttribute("readonly","");el.style.position="absolute";el.style.left="-9999px";document.body.appendChild(el);el.select();document.execCommand("copy");document.body.removeChild(el)}function copyButtonAnimation(button){button.classList.add("clicked");if(button.reset_button_timeout!==undefined){window.clearTimeout(button.reset_button_timeout)}button.reset_button_timeout=window.setTimeout(()=>{button.reset_button_timeout=undefined;button.classList.remove("clicked")},1000)}const but=document.getElementById("copy-path");if(!but){return}but.onclick=()=>{const title=document.querySelector("title").textContent.replace(" - Rust","");const[item,module]=title.split(" in ");const path=[item];if(module!==undefined){path.unshift(module)}copyContentToClipboard(path.join("::"));copyButtonAnimation(but)};function copyCode(codeElem){if(!codeElem){return}copyContentToClipboard(codeElem.textContent)}function getExampleWrap(event){let elem=event.target;while(!hasClass(elem,"example-wrap")){if(elem===document.body||elem.tagName==="A"||elem.tagName==="BUTTON"||hasClass(elem,"docblock")){return null}elem=elem.parentElement}return elem}function addCopyButton(event){const elem=getExampleWrap(event);if(elem===null){return}elem.removeEventListener("mouseover",addCopyButton);const parent=document.createElement("div");parent.className="button-holder";const runButton=elem.querySelector(".test-arrow");if(runButton!==null){parent.appendChild(runButton)}elem.appendChild(parent);const copyButton=document.createElement("button");copyButton.className="copy-button";copyButton.title="Copy code to clipboard";copyButton.addEventListener("click",()=>{copyCode(elem.querySelector("pre > code"));copyButtonAnimation(copyButton)});parent.appendChild(copyButton);if(!elem.parentElement.classList.contains("scraped-example")){return}const scrapedWrapped=elem.parentElement;window.updateScrapedExample(scrapedWrapped,parent)}function showHideCodeExampleButtons(event){const elem=getExampleWrap(event);if(elem===null){return}let buttons=elem.querySelector(".button-holder");if(buttons===null){addCopyButton(event);buttons=elem.querySelector(".button-holder");if(buttons===null){return}}buttons.classList.toggle("keep-visible")}onEachLazy(document.querySelectorAll(".docblock .example-wrap"),elem=>{elem.addEventListener("mouseover",addCopyButton);elem.addEventListener("click",showHideCodeExampleButtons)})}()) \ No newline at end of file diff --git a/static.files/normalize-76eba96aa4d2e634.css b/static.files/normalize-76eba96aa4d2e634.css new file mode 100644 index 0000000..469959f --- /dev/null +++ b/static.files/normalize-76eba96aa4d2e634.css @@ -0,0 +1,2 @@ + /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ +html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} \ No newline at end of file diff --git a/static.files/noscript-0111fcff984fae8f.css b/static.files/noscript-0111fcff984fae8f.css new file mode 100644 index 0000000..a6c18ec --- /dev/null +++ b/static.files/noscript-0111fcff984fae8f.css @@ -0,0 +1 @@ + #main-content .attributes{margin-left:0 !important;}#copy-path,#sidebar-button,.sidebar-resizer{display:none !important;}nav.sub{display:none;}.src .sidebar{display:none;}.notable-traits{display:none;}:root,:root:not([data-theme]){--main-background-color:white;--main-color:black;--settings-input-color:#2196f3;--settings-input-border-color:#717171;--settings-button-color:#000;--settings-button-border-focus:#717171;--sidebar-background-color:#f5f5f5;--sidebar-background-color-hover:#e0e0e0;--code-block-background-color:#f5f5f5;--scrollbar-track-background-color:#dcdcdc;--scrollbar-thumb-background-color:rgba(36,37,39,0.6);--scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;--headings-border-bottom-color:#ddd;--border-color:#e0e0e0;--button-background-color:#fff;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:none;--mobile-sidebar-menu-filter:none;--search-input-focused-border-color:#66afe9;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(35%);--code-example-button-color:#7f7f7f;--code-example-button-hover-color:#595959;--settings-menu-filter:invert(50%);--settings-menu-hover-filter:invert(35%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ad378a;--trait-link-color:#6e4fc9;--assoc-item-link-color:#3873ad;--function-link-color:#ad7c37;--macro-link-color:#068000;--keyword-link-color:#3873ad;--mod-link-color:#3873ad;--link-color:#3873ad;--sidebar-link-color:#356da4;--sidebar-current-link-background-color:#fff;--search-result-link-focus-background-color:#ccc;--search-result-border-color:#aaa3;--search-color:#000;--search-error-code-background-color:#d0cccc;--search-results-alias-color:#000;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#e6e6e6;--search-tab-button-not-selected-background:#e6e6e6;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#fff;--stab-background-color:#fff5d6;--stab-code-color:#000;--code-highlight-kw-color:#8959a8;--code-highlight-kw-2-color:#4271ae;--code-highlight-lifetime-color:#b76514;--code-highlight-prelude-color:#4271ae;--code-highlight-prelude-val-color:#c82829;--code-highlight-number-color:#718c00;--code-highlight-string-color:#718c00;--code-highlight-literal-color:#c82829;--code-highlight-attribute-color:#c82829;--code-highlight-self-color:#c82829;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8e908c;--code-highlight-doc-comment-color:#4d4d4c;--src-line-numbers-span-color:#c67e2d;--src-line-number-highlighted-background-color:#fdffd3;--target-background-color:#fdffd3;--target-border-color:#ad7c37;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:initial;--crate-search-div-filter:invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);--crate-search-div-hover-filter:invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);--crate-search-hover-border:#717171;--src-sidebar-background-selected:#fff;--src-sidebar-background-hover:#e0e0e0;--table-alt-row-background-color:#f5f5f5;--codeblock-link-background:#eee;--scrape-example-toggle-line-background:#ccc;--scrape-example-toggle-line-hover-background:#999;--scrape-example-code-line-highlight:#fcffd6;--scrape-example-code-line-highlight-focus:#f6fdb0;--scrape-example-help-border-color:#555;--scrape-example-help-color:#333;--scrape-example-help-hover-border-color:#000;--scrape-example-help-hover-color:#000;--scrape-example-code-wrapper-background-start:rgba(255,255,255,1);--scrape-example-code-wrapper-background-end:rgba(255,255,255,0);--sidebar-resizer-hover:hsl(207,90%,66%);--sidebar-resizer-active:hsl(207,90%,54%);}@media (prefers-color-scheme:dark){:root,:root:not([data-theme]){--main-background-color:#353535;--main-color:#ddd;--settings-input-color:#2196f3;--settings-input-border-color:#999;--settings-button-color:#000;--settings-button-border-focus:#ffb900;--sidebar-background-color:#505050;--sidebar-background-color-hover:#676767;--code-block-background-color:#2A2A2A;--scrollbar-track-background-color:#717171;--scrollbar-thumb-background-color:rgba(32,34,37,.6);--scrollbar-color:rgba(32,34,37,.6) #5a5a5a;--headings-border-bottom-color:#d2d2d2;--border-color:#e0e0e0;--button-background-color:#f0f0f0;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#008dfd;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(65%);--code-example-button-color:#7f7f7f;--code-example-button-hover-color:#a5a5a5;--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#2dbfb8;--trait-link-color:#b78cf2;--assoc-item-link-color:#d2991d;--function-link-color:#2bab63;--macro-link-color:#09bd00;--keyword-link-color:#d2991d;--mod-link-color:#d2991d;--link-color:#d2991d;--sidebar-link-color:#fdbf35;--sidebar-current-link-background-color:#444;--search-result-link-focus-background-color:#616161;--search-result-border-color:#aaa3;--search-color:#111;--search-error-code-background-color:#484848;--search-results-alias-color:#fff;--search-results-grey-color:#ccc;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#252525;--search-tab-button-not-selected-background:#252525;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#353535;--settings-menu-filter:invert(50%);--settings-menu-hover-filter:invert(65%);--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ab8ac1;--code-highlight-kw-2-color:#769acb;--code-highlight-lifetime-color:#d97f26;--code-highlight-prelude-color:#769acb;--code-highlight-prelude-val-color:#ee6868;--code-highlight-number-color:#83a300;--code-highlight-string-color:#83a300;--code-highlight-literal-color:#ee6868;--code-highlight-attribute-color:#ee6868;--code-highlight-self-color:#ee6868;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8d8d8b;--code-highlight-doc-comment-color:#8ca375;--src-line-numbers-span-color:#3b91e2;--src-line-number-highlighted-background-color:#0a042f;--target-background-color:#494a3d;--target-border-color:#bb7410;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);--crate-search-div-hover-filter:invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);--crate-search-hover-border:#2196f3;--src-sidebar-background-selected:#333;--src-sidebar-background-hover:#444;--table-alt-row-background-color:#2a2a2a;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(53,53,53,1);--scrape-example-code-wrapper-background-end:rgba(53,53,53,0);--sidebar-resizer-hover:hsl(207,30%,54%);--sidebar-resizer-active:hsl(207,90%,54%);}} \ No newline at end of file diff --git a/static.files/rust-logo-151179464ae7ed46.svg b/static.files/rust-logo-151179464ae7ed46.svg new file mode 100644 index 0000000..62424d8 --- /dev/null +++ b/static.files/rust-logo-151179464ae7ed46.svg @@ -0,0 +1,61 @@ + + + diff --git a/static.files/rustdoc-b0742ba02757f159.css b/static.files/rustdoc-b0742ba02757f159.css new file mode 100644 index 0000000..9fef311 --- /dev/null +++ b/static.files/rustdoc-b0742ba02757f159.css @@ -0,0 +1,53 @@ + :root{--nav-sub-mobile-padding:8px;--search-typename-width:6.75rem;--desktop-sidebar-width:200px;--src-sidebar-width:300px;--desktop-sidebar-z-index:100;--sidebar-elems-left-padding:24px;--clipboard-image:url('data:image/svg+xml,\ +\ +\ +');--copy-path-height:34px;--copy-path-width:33px;--checkmark-image:url('data:image/svg+xml,\ +\ +');--button-left-margin:4px;--button-border-radius:2px;--toolbar-button-border-radius:6px;--code-block-border-radius:6px;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:400;src:local('Source Serif 4'),url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:italic;font-weight:400;src:local('Source Serif 4 Italic'),url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:700;src:local('Source Serif 4 Bold'),url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:italic;font-weight:400;src:url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'NanumBarunGothic';src:url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2");font-display:swap;unicode-range:U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF;}*{box-sizing:border-box;}body{font:1rem/1.5 "Source Serif 4",NanumBarunGothic,serif;margin:0;position:relative;overflow-wrap:break-word;overflow-wrap:anywhere;font-feature-settings:"kern","liga";background-color:var(--main-background-color);color:var(--main-color);}h1{font-size:1.5rem;}h2{font-size:1.375rem;}h3{font-size:1.25rem;}h1,h2,h3,h4,h5,h6{font-weight:500;}h1,h2,h3,h4{margin:25px 0 15px 0;padding-bottom:6px;}.docblock h3,.docblock h4,h5,h6{margin:15px 0 5px 0;}.docblock>h2:first-child,.docblock>h3:first-child,.docblock>h4:first-child,.docblock>h5:first-child,.docblock>h6:first-child{margin-top:0;}.main-heading h1{margin:0;padding:0;grid-area:main-heading-h1;overflow-wrap:break-word;overflow-wrap:anywhere;}.main-heading{position:relative;display:grid;grid-template-areas:"main-heading-breadcrumbs main-heading-breadcrumbs" "main-heading-h1 main-heading-toolbar" "main-heading-sub-heading main-heading-toolbar";grid-template-columns:minmax(105px,1fr) minmax(0,max-content);grid-template-rows:minmax(25px,min-content) min-content min-content;padding-bottom:6px;margin-bottom:11px;}.rustdoc-breadcrumbs{grid-area:main-heading-breadcrumbs;line-height:1.25;display:flex;flex-wrap:wrap;align-items:end;padding-top:5px;}.rustdoc-breadcrumbs a{padding:4px 0;margin:-4px 0;z-index:1;}.content h2,.top-doc .docblock>h3,.top-doc .docblock>h4{border-bottom:1px solid var(--headings-border-bottom-color);}h1,h2{line-height:1.25;padding-top:3px;padding-bottom:9px;}h3.code-header{font-size:1.125rem;}h4.code-header{font-size:1rem;}.code-header{font-weight:600;margin:0;padding:0;white-space:pre-wrap;}.structfield{margin:0.6em 0;}#crate-search,h1,h2,h3,h4,h5,h6,.sidebar,.mobile-topbar,.search-input,.search-results .result-name,.item-name>a,.out-of-band,.sub-heading,span.since,a.src,rustdoc-toolbar,summary.hideme,.scraped-example-list,.rustdoc-breadcrumbs,ul.all-items{font-family:"Fira Sans",Arial,NanumBarunGothic,sans-serif;}#toggle-all-docs,a.anchor,.section-header a,#src-sidebar a,.rust a,.sidebar h2 a,.sidebar h3 a,.mobile-topbar h2 a,h1 a,.search-results a,.stab,.result-name i{color:var(--main-color);}span.enum,a.enum,span.struct,a.struct,span.union,a.union,span.primitive,a.primitive,span.type,a.type,span.foreigntype,a.foreigntype{color:var(--type-link-color);}span.trait,a.trait,span.traitalias,a.traitalias{color:var(--trait-link-color);}span.associatedtype,a.associatedtype,span.constant,a.constant,span.static,a.static{color:var(--assoc-item-link-color);}span.fn,a.fn,span.method,a.method,span.tymethod,a.tymethod{color:var(--function-link-color);}span.attr,a.attr,span.derive,a.derive,span.macro,a.macro{color:var(--macro-link-color);}span.mod,a.mod{color:var(--mod-link-color);}span.keyword,a.keyword{color:var(--keyword-link-color);}a{color:var(--link-color);text-decoration:none;}ol,ul{padding-left:24px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.625em;}p,.docblock>.warning{margin:0 0 .75em 0;}p:last-child,.docblock>.warning:last-child{margin:0;}button{padding:1px 6px;cursor:pointer;}button#toggle-all-docs{padding:0;background:none;border:none;-webkit-appearance:none;opacity:1;}.rustdoc{display:flex;flex-direction:row;flex-wrap:nowrap;}main{position:relative;flex-grow:1;padding:10px 15px 40px 45px;min-width:0;}.src main{padding:15px;}.width-limiter{max-width:960px;margin-right:auto;}details:not(.toggle) summary{margin-bottom:.6em;}code,pre,.code-header{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.125em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;line-height:1.5;}pre.item-decl{overflow-x:auto;}.item-decl .type-contents-toggle{contain:initial;}.src .content pre{padding:20px;}.rustdoc.src .example-wrap .src-line-numbers{padding:20px 0 20px 4px;}img{max-width:100%;}.logo-container{line-height:0;display:block;}.rust-logo{filter:var(--rust-logo-filter);}.sidebar{font-size:0.875rem;flex:0 0 var(--desktop-sidebar-width);width:var(--desktop-sidebar-width);overflow-y:scroll;overscroll-behavior:contain;position:sticky;height:100vh;top:0;left:0;z-index:var(--desktop-sidebar-z-index);}.rustdoc.src .sidebar{flex-basis:50px;width:50px;border-right:1px solid;overflow-x:hidden;overflow-y:hidden;}.hide-sidebar .sidebar,.hide-sidebar .sidebar-resizer{display:none;}.sidebar-resizer{touch-action:none;width:9px;cursor:col-resize;z-index:calc(var(--desktop-sidebar-z-index) + 1);position:fixed;height:100%;left:calc(var(--desktop-sidebar-width) + 1px);}.rustdoc.src .sidebar-resizer{left:49px;}.src-sidebar-expanded .src .sidebar-resizer{left:var(--src-sidebar-width);}.sidebar-resizing{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;}.sidebar-resizing*{cursor:col-resize !important;}.sidebar-resizing .sidebar{position:fixed;}.sidebar-resizing>body{padding-left:var(--resizing-sidebar-width);}.sidebar-resizer:hover,.sidebar-resizer:active,.sidebar-resizer:focus,.sidebar-resizer.active{width:10px;margin:0;left:var(--desktop-sidebar-width);border-left:solid 1px var(--sidebar-resizer-hover);}.src-sidebar-expanded .rustdoc.src .sidebar-resizer:hover,.src-sidebar-expanded .rustdoc.src .sidebar-resizer:active,.src-sidebar-expanded .rustdoc.src .sidebar-resizer:focus,.src-sidebar-expanded .rustdoc.src .sidebar-resizer.active{left:calc(var(--src-sidebar-width) - 1px);}@media (pointer:coarse){.sidebar-resizer{display:none !important;}}.sidebar-resizer.active{padding:0 140px;width:2px;margin-left:-140px;border-left:none;}.sidebar-resizer.active:before{border-left:solid 2px var(--sidebar-resizer-active);display:block;height:100%;content:"";}.sidebar,.mobile-topbar,.sidebar-menu-toggle,#src-sidebar{background-color:var(--sidebar-background-color);}.src .sidebar>*{visibility:hidden;}.src-sidebar-expanded .src .sidebar{overflow-y:auto;flex-basis:var(--src-sidebar-width);width:var(--src-sidebar-width);}.src-sidebar-expanded .src .sidebar>*{visibility:visible;}#all-types{margin-top:1em;}*{scrollbar-width:initial;scrollbar-color:var(--scrollbar-color);}.sidebar{scrollbar-width:thin;scrollbar-color:var(--scrollbar-color);}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;background-color:var(--scrollbar-track-background-color);}.sidebar::-webkit-scrollbar-track{background-color:var(--scrollbar-track-background-color);}::-webkit-scrollbar-thumb,.sidebar::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb-background-color);}.hidden{display:none !important;}.logo-container>img{height:48px;width:48px;}ul.block,.block li,.block ul{padding:0;margin:0;list-style:none;}.block ul a{padding-left:1rem;}.sidebar-elems a,.sidebar>h2 a{display:block;padding:0.25rem;margin-right:0.25rem;border-left:solid var(--sidebar-elems-left-padding) transparent;margin-left:calc(-0.25rem - var(--sidebar-elems-left-padding));background-clip:border-box;}.hide-toc #rustdoc-toc,.hide-toc .in-crate{display:none;}.hide-modnav #rustdoc-modnav{display:none;}.sidebar h2{text-wrap:balance;overflow-wrap:anywhere;padding:0;margin:0.7rem 0;}.sidebar h3{text-wrap:balance;overflow-wrap:anywhere;font-size:1.125rem;padding:0;margin:0;}.sidebar-elems,.sidebar>.version,.sidebar>h2{padding-left:var(--sidebar-elems-left-padding);}.sidebar a{color:var(--sidebar-link-color);}.sidebar .current,.sidebar .current a,.sidebar-crate a.logo-container:hover+h2 a,.sidebar a:hover:not(.logo-container){background-color:var(--sidebar-current-link-background-color);}.sidebar-elems .block{margin-bottom:2em;}.sidebar-elems .block li a{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;}.sidebar-crate{display:flex;align-items:center;justify-content:center;margin:14px 32px 1rem;row-gap:10px;column-gap:32px;flex-wrap:wrap;}.sidebar-crate h2{flex-grow:1;margin:0 -8px;align-self:start;}.sidebar-crate .logo-container{margin:0 calc(-16px - var(--sidebar-elems-left-padding));padding:0 var(--sidebar-elems-left-padding);text-align:center;}.sidebar-crate .logo-container img{margin-top:-16px;border-top:solid 16px transparent;box-sizing:content-box;position:relative;background-clip:border-box;z-index:1;}.sidebar-crate h2 a{display:block;border-left:solid var(--sidebar-elems-left-padding) transparent;background-clip:border-box;margin:0 calc(-24px + 0.25rem) 0 calc(-0.2rem - var(--sidebar-elems-left-padding));padding:calc((16px - 0.57rem ) / 2 ) 0.25rem;padding-left:0.2rem;}.sidebar-crate h2 .version{display:block;font-weight:normal;font-size:1rem;overflow-wrap:break-word;}.sidebar-crate+.version{margin-top:-1rem;margin-bottom:1rem;}.mobile-topbar{display:none;}.rustdoc .example-wrap{display:flex;position:relative;margin-bottom:10px;}.rustdoc .example-wrap>pre,.rustdoc .scraped-example .src-line-numbers,.rustdoc .scraped-example .src-line-numbers>pre{border-radius:6px;}.rustdoc .example-wrap>.example-line-numbers,.rustdoc .scraped-example .src-line-numbers,.rustdoc .scraped-example .src-line-numbers>pre{border-top-right-radius:0;border-bottom-right-radius:0;}.rustdoc .example-wrap>.example-line-numbers+pre,.rustdoc .scraped-example .rust{border-top-left-radius:0;border-bottom-left-radius:0;}.rustdoc .scraped-example{position:relative;}.rustdoc .example-wrap:last-child{margin-bottom:0px;}.rustdoc .example-wrap pre{margin:0;flex-grow:1;}.scraped-example:not(.expanded) .example-wrap{max-height:calc(1.5em * 5 + 10px);}.more-scraped-examples .scraped-example:not(.expanded) .example-wrap{max-height:calc(1.5em * 10 + 10px);}.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers,.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers>pre,.rustdoc:not(.src) .scraped-example:not(.expanded) pre.rust{padding-bottom:0;overflow:auto hidden;}.rustdoc:not(.src) .scraped-example .src-line-numbers{padding-top:0;}.rustdoc:not(.src) .scraped-example.expanded .src-line-numbers{padding-bottom:0;}.rustdoc:not(.src) .example-wrap pre{overflow:auto;}.rustdoc .example-wrap pre.example-line-numbers,.rustdoc .example-wrap .src-line-numbers{min-width:fit-content;flex-grow:0;text-align:right;-webkit-user-select:none;user-select:none;padding:14px 8px;padding-right:2px;color:var(--src-line-numbers-span-color);}.rustdoc .scraped-example .example-wrap .src-line-numbers{padding:0;}.rustdoc .src-line-numbers pre{padding:14px 0;}.src-line-numbers a,.src-line-numbers span{color:var(--src-line-numbers-span-color);padding:0 8px;}.src-line-numbers :target{background-color:transparent;border-right:none;padding:0 8px;}.src-line-numbers .line-highlighted{background-color:var(--src-line-number-highlighted-background-color);}.search-loading{text-align:center;}.docblock-short{overflow-wrap:break-word;overflow-wrap:anywhere;}.docblock :not(pre)>code,.docblock-short code{white-space:pre-wrap;}.top-doc .docblock h2{font-size:1.375rem;}.top-doc .docblock h3{font-size:1.25rem;}.top-doc .docblock h4,.top-doc .docblock h5{font-size:1.125rem;}.top-doc .docblock h6{font-size:1rem;}.docblock h5{font-size:1rem;}.docblock h6{font-size:0.875rem;}.docblock{margin-left:24px;position:relative;}.docblock>:not(.more-examples-toggle):not(.example-wrap){max-width:100%;overflow-x:auto;}.sub-heading{font-size:1rem;flex-grow:0;grid-area:main-heading-sub-heading;line-height:1.25;padding-bottom:4px;}.main-heading rustdoc-toolbar,.main-heading .out-of-band{grid-area:main-heading-toolbar;}rustdoc-toolbar{display:flex;flex-direction:row;flex-wrap:nowrap;min-height:60px;}.docblock code,.docblock-short code,pre,.rustdoc.src .example-wrap,.example-wrap .src-line-numbers{background-color:var(--code-block-background-color);border-radius:var(--code-block-border-radius);}#main-content{position:relative;}.docblock table{margin:.5em 0;border-collapse:collapse;}.docblock table td,.docblock table th{padding:.5em;border:1px solid var(--border-color);}.docblock table tbody tr:nth-child(2n){background:var(--table-alt-row-background-color);}.docblock .stab,.docblock-short .stab{display:inline-block;}.docblock li{margin-bottom:.4em;}.docblock li p:not(:last-child){margin-bottom:.3em;}div.where{white-space:pre-wrap;font-size:0.875rem;}.item-info{display:block;margin-left:24px;}.item-info code{font-size:0.875rem;}#main-content>.item-info{margin-left:0;}nav.sub{flex-grow:1;flex-flow:row nowrap;margin:4px 0 0 0;display:flex;align-items:center;}.search-form{position:relative;display:flex;height:34px;flex-grow:1;}.src nav.sub{margin:0 0 -10px 0;}.section-header{display:block;position:relative;}.section-header:hover>.anchor,.impl:hover>.anchor,.trait-impl:hover>.anchor,.variant:hover>.anchor{display:initial;}.anchor{display:none;position:absolute;left:-0.5em;background:none !important;}.anchor.field{left:-5px;}.section-header>.anchor{left:-15px;padding-right:8px;}h2.section-header>.anchor{padding-right:6px;}a.doc-anchor{color:var(--main-color);display:none;position:absolute;left:-17px;padding-right:10px;padding-left:3px;}*:hover>.doc-anchor{display:block;}.top-doc>.docblock>*:first-child>.doc-anchor{display:none !important;}.main-heading a:hover,.example-wrap .rust a:hover,.all-items a:hover,.docblock a:not(.scrape-help):not(.tooltip):hover:not(.doc-anchor),.docblock-short a:not(.scrape-help):not(.tooltip):hover,.item-info a{text-decoration:underline;}.crate.block li.current a{font-weight:500;}table,.item-table{overflow-wrap:break-word;}.item-table{display:table;padding:0;margin:0;width:100%;}.item-table>li{display:table-row;}.item-table>li>div{display:table-cell;}.item-table>li>.item-name{padding-right:1.25rem;}.search-results-title{margin-top:0;white-space:nowrap;display:flex;align-items:baseline;}.search-results-title+.sub-heading{color:var(--main-color);display:flex;align-items:baseline;white-space:nowrap;}#crate-search-div{position:relative;min-width:0;}#crate-search{padding:0 23px 0 4px;max-width:100%;text-overflow:ellipsis;border:1px solid var(--border-color);border-radius:4px;outline:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;background-color:var(--main-background-color);color:inherit;line-height:1.5;font-weight:500;}#crate-search:hover,#crate-search:focus{border-color:var(--crate-search-hover-border);}#crate-search-div::after{pointer-events:none;width:100%;height:100%;position:absolute;top:0;left:0;content:"";background-repeat:no-repeat;background-size:20px;background-position:calc(100% - 2px) 56%;background-image:url('data:image/svg+xml, \ + ');filter:var(--crate-search-div-filter);}#crate-search-div:hover::after,#crate-search-div:focus-within::after{filter:var(--crate-search-div-hover-filter);}#crate-search>option{font-size:1rem;}.search-input{-webkit-appearance:none;outline:none;border:1px solid var(--border-color);border-radius:2px;padding:8px;font-size:1rem;flex-grow:1;background-color:var(--button-background-color);color:var(--search-color);}.search-input:focus{border-color:var(--search-input-focused-border-color);}.search-results{display:none;}.search-results.active{display:block;}.search-results>a{display:flex;margin-left:2px;margin-right:2px;border-bottom:1px solid var(--search-result-border-color);gap:1em;}.search-results>a>div.desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex:2;}.search-results a:hover,.search-results a:focus{background-color:var(--search-result-link-focus-background-color);}.search-results .result-name{display:flex;align-items:center;justify-content:start;flex:3;}.search-results .result-name .alias{color:var(--search-results-alias-color);}.search-results .result-name .grey{color:var(--search-results-grey-color);}.search-results .result-name .typename{color:var(--search-results-grey-color);font-size:0.875rem;width:var(--search-typename-width);}.search-results .result-name .path{word-break:break-all;max-width:calc(100% - var(--search-typename-width));display:inline-block;}.search-results .result-name .path>*{display:inline;}.popover{position:absolute;top:100%;right:0;z-index:calc(var(--desktop-sidebar-z-index) + 1);margin-top:7px;border-radius:3px;border:1px solid var(--border-color);background-color:var(--main-background-color);color:var(--main-color);--popover-arrow-offset:11px;}.popover::before{content:'';position:absolute;right:var(--popover-arrow-offset);border:solid var(--border-color);border-width:1px 1px 0 0;background-color:var(--main-background-color);padding:4px;transform:rotate(-45deg);top:-5px;}.setting-line{margin:1.2em 0.6em;}.setting-radio input,.setting-check input{margin-right:0.3em;height:1.2rem;width:1.2rem;border:2px solid var(--settings-input-border-color);outline:none;-webkit-appearance:none;cursor:pointer;}.setting-radio input{border-radius:50%;}.setting-radio span,.setting-check span{padding-bottom:1px;}.setting-radio{margin-top:0.1em;margin-bottom:0.1em;min-width:3.8em;padding:0.3em;display:inline-flex;align-items:center;cursor:pointer;}.setting-radio+.setting-radio{margin-left:0.5em;}.setting-check{margin-right:20px;display:flex;align-items:center;cursor:pointer;}.setting-radio input:checked{box-shadow:inset 0 0 0 3px var(--main-background-color);background-color:var(--settings-input-color);}.setting-check input:checked{background-color:var(--settings-input-color);border-width:1px;content:url('data:image/svg+xml,\ + \ + ');}.setting-radio input:focus,.setting-check input:focus{box-shadow:0 0 1px 1px var(--settings-input-color);}.setting-radio input:checked:focus{box-shadow:inset 0 0 0 3px var(--main-background-color),0 0 2px 2px var(--settings-input-color);}.setting-radio input:hover,.setting-check input:hover{border-color:var(--settings-input-color) !important;}#settings.popover{--popover-arrow-offset:202px;top:calc(100% - 16px);}#help.popover{max-width:600px;--popover-arrow-offset:118px;top:calc(100% - 16px);}#help dt{float:left;clear:left;margin-right:0.5rem;}#help dd{margin-bottom:0.5rem;}#help span.top,#help span.bottom{text-align:center;display:block;font-size:1.125rem;padding:0 0.5rem;text-wrap-style:balance;}#help span.top{margin:10px 0;border-bottom:1px solid var(--border-color);padding-bottom:4px;margin-bottom:6px;}#help span.bottom{clear:both;border-top:1px solid var(--border-color);}.side-by-side{display:flex;margin-bottom:20px;}.side-by-side>div{width:50%;padding:0 20px 0 17px;}.item-info .stab{display:block;padding:3px;margin-bottom:5px;}.item-name .stab{margin-left:0.3125em;}.stab{padding:0 2px;font-size:0.875rem;font-weight:normal;color:var(--main-color);background-color:var(--stab-background-color);width:fit-content;white-space:pre-wrap;border-radius:3px;display:inline;vertical-align:baseline;}.stab.portability>code{background:none;color:var(--stab-code-color);}.stab .emoji,.item-info .stab::before{font-size:1.25rem;}.stab .emoji{margin-right:0.3rem;}.item-info .stab::before{content:"\0";width:0;display:inline-block;color:transparent;}.emoji{text-shadow:1px 0 0 black,-1px 0 0 black,0 1px 0 black,0 -1px 0 black;}.since{font-weight:normal;font-size:initial;}.rightside{padding-left:12px;float:right;}.rightside:not(a),.out-of-band,.sub-heading,rustdoc-toolbar{color:var(--right-side-color);}pre.rust{tab-size:4;-moz-tab-size:4;}pre.rust .kw{color:var(--code-highlight-kw-color);}pre.rust .kw-2{color:var(--code-highlight-kw-2-color);}pre.rust .lifetime{color:var(--code-highlight-lifetime-color);}pre.rust .prelude-ty{color:var(--code-highlight-prelude-color);}pre.rust .prelude-val{color:var(--code-highlight-prelude-val-color);}pre.rust .string{color:var(--code-highlight-string-color);}pre.rust .number{color:var(--code-highlight-number-color);}pre.rust .bool-val{color:var(--code-highlight-literal-color);}pre.rust .self{color:var(--code-highlight-self-color);}pre.rust .attr{color:var(--code-highlight-attribute-color);}pre.rust .macro,pre.rust .macro-nonterminal{color:var(--code-highlight-macro-color);}pre.rust .question-mark{font-weight:bold;color:var(--code-highlight-question-mark-color);}pre.rust .comment{color:var(--code-highlight-comment-color);}pre.rust .doccomment{color:var(--code-highlight-doc-comment-color);}.rustdoc.src .example-wrap pre.rust a{background:var(--codeblock-link-background);}.example-wrap.compile_fail,.example-wrap.should_panic{border-left:2px solid var(--codeblock-error-color);}.ignore.example-wrap{border-left:2px solid var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover,.example-wrap.should_panic:hover{border-left:2px solid var(--codeblock-error-hover-color);}.example-wrap.ignore:hover{border-left:2px solid var(--codeblock-ignore-hover-color);}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip{color:var(--codeblock-error-color);}.example-wrap.ignore .tooltip{color:var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover .tooltip,.example-wrap.should_panic:hover .tooltip{color:var(--codeblock-error-hover-color);}.example-wrap.ignore:hover .tooltip{color:var(--codeblock-ignore-hover-color);}.example-wrap .tooltip{position:absolute;display:block;left:-25px;top:5px;margin:0;line-height:1;}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip,.example-wrap.ignore .tooltip{font-weight:bold;font-size:1.25rem;}.content .docblock .warning{border-left:2px solid var(--warning-border-color);padding:14px;position:relative;overflow-x:visible !important;}.content .docblock .warning::before{color:var(--warning-border-color);content:"ⓘ";position:absolute;left:-25px;top:5px;font-weight:bold;font-size:1.25rem;}.top-doc>.docblock>.warning:first-child::before{top:20px;}.example-wrap>a.test-arrow,.example-wrap .button-holder{visibility:hidden;position:absolute;top:4px;right:4px;z-index:1;}a.test-arrow{height:var(--copy-path-height);padding:6px 4px 0 11px;}a.test-arrow::before{content:url('data:image/svg+xml,');}.example-wrap .button-holder{display:flex;}@media not (pointer:coarse){.example-wrap:hover>a.test-arrow,.example-wrap:hover>.button-holder{visibility:visible;}}.example-wrap .button-holder.keep-visible{visibility:visible;}.example-wrap .button-holder>*{background:var(--main-background-color);cursor:pointer;border-radius:var(--button-border-radius);height:var(--copy-path-height);width:var(--copy-path-width);border:0;color:var(--code-example-button-color);}.example-wrap .button-holder>*:hover{color:var(--code-example-button-hover-color);}.example-wrap .button-holder>*:not(:first-child){margin-left:var(--button-left-margin);}.example-wrap .button-holder .copy-button{padding:2px 0 0 4px;}.example-wrap .button-holder .copy-button::before,.example-wrap .test-arrow::before{filter:var(--copy-path-img-filter);}.example-wrap .button-holder .copy-button::before{content:var(--clipboard-image);}.example-wrap .button-holder .copy-button:hover::before,.example-wrap .test-arrow:hover::before{filter:var(--copy-path-img-hover-filter);}.example-wrap .button-holder .copy-button.clicked::before{content:var(--checkmark-image);padding-right:5px;}.code-attribute{font-weight:300;color:var(--code-attribute-color);}.item-spacer{width:100%;height:12px;display:block;}.main-heading span.since::before{content:"Since ";}.sub-variant h4{font-size:1rem;font-weight:400;margin-top:0;margin-bottom:0;}.sub-variant{margin-left:24px;margin-bottom:40px;}.sub-variant>.sub-variant-field{margin-left:24px;}@keyframes targetfadein{from{background-color:var(--main-background-color);}10%{background-color:var(--target-border-color);}to{background-color:var(--target-background-color);}}:target{padding-right:3px;background-color:var(--target-background-color);border-right:3px solid var(--target-border-color);}.code-header a.tooltip{color:inherit;margin-right:15px;position:relative;}.code-header a.tooltip:hover{color:var(--link-color);}a.tooltip:hover::after{position:absolute;top:calc(100% - 10px);left:-15px;right:-15px;height:20px;content:"\00a0";}@media not (prefers-reduced-motion){:target{animation:0.65s cubic-bezier(0,0,0.1,1.0) 0.1s targetfadein;}.fade-out{opacity:0;transition:opacity 0.45s cubic-bezier(0,0,0.1,1.0);}}.popover.tooltip .content{margin:0.25em 0.5em;}.popover.tooltip .content pre,.popover.tooltip .content code{background:transparent;margin:0;padding:0;font-size:1.25rem;white-space:pre-wrap;}.popover.tooltip .content>h3:first-child{margin:0 0 5px 0;}.search-failed{text-align:center;margin-top:20px;display:none;}.search-failed.active{display:block;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#search-tabs{margin-top:0.25rem;display:flex;flex-direction:row;gap:1px;margin-bottom:4px;}#search-tabs button{text-align:center;font-size:1.125rem;border:0;border-top:2px solid;flex:1;line-height:1.5;color:inherit;}#search-tabs button:not(.selected){background-color:var(--search-tab-button-not-selected-background);border-top-color:var(--search-tab-button-not-selected-border-top-color);}#search-tabs button:hover,#search-tabs button.selected{background-color:var(--search-tab-button-selected-background);border-top-color:var(--search-tab-button-selected-border-top-color);}#search-tabs .count{font-size:1rem;font-variant-numeric:tabular-nums;color:var(--search-tab-title-count-color);}#search .error code{border-radius:3px;background-color:var(--search-error-code-background-color);}.search-corrections{font-weight:normal;}#src-sidebar{width:100%;overflow:auto;}#src-sidebar div.files>a:hover,details.dir-entry summary:hover,#src-sidebar div.files>a:focus,details.dir-entry summary:focus{background-color:var(--src-sidebar-background-hover);}#src-sidebar div.files>a.selected{background-color:var(--src-sidebar-background-selected);}.src-sidebar-title{position:sticky;top:0;display:flex;padding:8px 8px 0 48px;margin-bottom:7px;background:var(--sidebar-background-color);border-bottom:1px solid var(--border-color);}#settings-menu,#help-button,button#toggle-all-docs{margin-left:var(--button-left-margin);display:flex;line-height:1.25;min-width:14px;}#sidebar-button{display:none;line-height:0;}.hide-sidebar #sidebar-button,.src #sidebar-button{display:flex;margin-right:4px;position:fixed;left:6px;height:34px;width:34px;background-color:var(--main-background-color);z-index:1;}.src #sidebar-button{left:8px;z-index:calc(var(--desktop-sidebar-z-index) + 1);}.hide-sidebar .src #sidebar-button{position:static;}#settings-menu>a,#help-button>a,#sidebar-button>a,button#toggle-all-docs{display:flex;align-items:center;justify-content:center;flex-direction:column;border:1px solid transparent;border-radius:var(--button-border-radius);color:var(--main-color);}#settings-menu>a,#help-button>a,button#toggle-all-docs{width:80px;border-radius:var(--toolbar-button-border-radius);}#settings-menu>a,#help-button>a{min-width:0;}#sidebar-button>a{background-color:var(--button-background-color);border-color:var(--border-color);width:33px;}#settings-menu>a:hover,#settings-menu>a:focus-visible,#help-button>a:hover,#help-button>a:focus-visible,#sidebar-button>a:hover,#sidebar-button>a:focus-visible,button#toggle-all-docs:hover,button#toggle-all-docs:focus-visible{border-color:var(--settings-button-border-focus);text-decoration:none;}#settings-menu>a:before{content:url('data:image/svg+xml,\ + ');width:18px;height:18px;filter:var(--settings-menu-filter);}button#toggle-all-docs:before{content:url('data:image/svg+xml,\ + ');width:18px;height:18px;filter:var(--settings-menu-filter);}#help-button>a:before{content:url('data:image/svg+xml,\ + \ + ?');width:18px;height:18px;filter:var(--settings-menu-filter);}button#toggle-all-docs:before,#help-button>a:before,#settings-menu>a:before{filter:var(--settings-menu-filter);margin:8px;}@media not (pointer:coarse){button#toggle-all-docs:hover:before,#help-button>a:hover:before,#settings-menu>a:hover:before{filter:var(--settings-menu-hover-filter);}}button[disabled]#toggle-all-docs{opacity:0.25;border:solid 1px var(--main-background-color);background-size:cover;}button[disabled]#toggle-all-docs:hover{border:solid 1px var(--main-background-color);cursor:not-allowed;}rustdoc-toolbar span.label{font-size:1rem;flex-grow:1;padding-bottom:4px;}#sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');width:22px;height:22px;}#copy-path{color:var(--copy-path-button-color);background:var(--main-background-color);height:var(--copy-path-height);width:var(--copy-path-width);margin-left:10px;padding:0;padding-left:2px;border:0;font-size:0;}#copy-path::before{filter:var(--copy-path-img-filter);content:var(--clipboard-image);}#copy-path:hover::before{filter:var(--copy-path-img-hover-filter);}#copy-path.clicked::before{content:var(--checkmark-image);}@keyframes rotating{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}#settings-menu.rotate>a img{animation:rotating 2s linear infinite;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px var(--border-color);border-radius:3px;color:var(--kbd-color);background-color:var(--kbd-background);box-shadow:inset 0 -1px 0 var(--kbd-box-shadow-color);}ul.all-items>li{list-style:none;}details.dir-entry{padding-left:4px;}details.dir-entry>summary{margin:0 0 0 -4px;padding:0 0 0 4px;cursor:pointer;}details.dir-entry div.folders,details.dir-entry div.files{padding-left:23px;}details.dir-entry a{display:block;}details.toggle{contain:layout;position:relative;}details.big-toggle{contain:inline-size;}details.toggle>summary.hideme{cursor:pointer;font-size:1rem;}details.toggle>summary{list-style:none;outline:none;}details.toggle>summary::-webkit-details-marker,details.toggle>summary::marker{display:none;}details.toggle>summary.hideme>span{margin-left:9px;}details.toggle>summary::before{background:url('data:image/svg+xml,\ + ');content:"";cursor:pointer;width:16px;height:16px;display:inline-block;vertical-align:middle;opacity:.5;filter:var(--toggle-filter);}details.toggle>summary.hideme>span,.more-examples-toggle summary,.more-examples-toggle .hide-more{color:var(--toggles-color);}details.toggle>summary::after{content:"Expand";overflow:hidden;width:0;height:0;position:absolute;}details.toggle>summary.hideme::after{content:"";}details.toggle>summary:focus::before,details.toggle>summary:hover::before{opacity:1;}details.toggle>summary:focus-visible::before{outline:1px dotted #000;outline-offset:1px;}details.non-exhaustive{margin-bottom:8px;}details.toggle>summary.hideme::before{position:relative;}details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;top:4px;}.impl-items>details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;}details.big-toggle>summary:not(.hideme)::before{left:-34px;top:9px;}details.toggle[open] >summary.hideme{position:absolute;}details.toggle[open] >summary.hideme>span{display:none;}details.toggle[open] >summary::before{background:url('data:image/svg+xml,\ + ');}details.toggle[open] >summary::after{content:"Collapse";}.docblock summary>*{display:inline-block;}.docblock>.example-wrap:first-child .tooltip{margin-top:16px;}.src #sidebar-button>a:before,.sidebar-menu-toggle:before{content:url('data:image/svg+xml,\ + ');opacity:0.75;}.sidebar-menu-toggle:hover:before,.sidebar-menu-toggle:active:before,.sidebar-menu-toggle:focus:before{opacity:1;}.src #sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');opacity:0.75;}@media (max-width:850px){#search-tabs .count{display:block;}.side-by-side{flex-direction:column-reverse;}.side-by-side>div{width:auto;}}@media (max-width:700px){*[id]{scroll-margin-top:45px;}#copy-path{display:none;}rustdoc-toolbar span.label{display:none;}#settings-menu>a,#help-button>a,button#toggle-all-docs{width:33px;}#settings.popover{--popover-arrow-offset:86px;}#help.popover{--popover-arrow-offset:48px;}.rustdoc{display:block;}main{padding-left:15px;padding-top:0px;}.sidebar .logo-container,.sidebar .location,.sidebar-resizer{display:none;}.sidebar{position:fixed;top:45px;left:-1000px;z-index:11;height:calc(100vh - 45px);width:200px;}.src main,.rustdoc.src .sidebar{top:0;padding:0;height:100vh;border:0;}.src .search-form{margin-left:40px;}.src .main-heading{margin-left:8px;}.hide-sidebar .search-form{margin-left:32px;}.hide-sidebar .src .search-form{margin-left:0;}.sidebar.shown,.src-sidebar-expanded .src .sidebar,.rustdoc:not(.src) .sidebar:focus-within{left:0;}.mobile-topbar h2{padding-bottom:0;margin:auto 0.5em auto auto;overflow:hidden;font-size:24px;white-space:nowrap;text-overflow:ellipsis;}.mobile-topbar .logo-container>img{max-width:35px;max-height:35px;margin:5px 0 5px 20px;}.mobile-topbar{display:flex;flex-direction:row;position:sticky;z-index:10;font-size:2rem;height:45px;width:100%;left:0;top:0;}.hide-sidebar .mobile-topbar{display:none;}.sidebar-menu-toggle{width:45px;border:none;line-height:0;}.hide-sidebar .sidebar-menu-toggle{display:none;}.sidebar-elems{margin-top:1em;}.anchor{display:none !important;}#main-content>details.toggle>summary::before,#main-content>div>details.toggle>summary::before{left:-11px;}#sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');width:22px;height:22px;}.sidebar-menu-toggle:before{filter:var(--mobile-sidebar-menu-filter);}.sidebar-menu-toggle:hover{background:var(--main-background-color);}.item-table,.item-row,.item-table>li,.item-table>li>div,.search-results>a,.search-results>a>div{display:block;}.search-results>a{padding:5px 0px;}.search-results>a>div.desc,.item-table>li>div.desc{padding-left:2em;}.search-results .result-name{display:block;}.search-results .result-name .typename{width:initial;margin-right:0;}.search-results .result-name .typename,.search-results .result-name .path{display:inline;}.src-sidebar-expanded .src .sidebar{position:fixed;max-width:100vw;width:100vw;}.src .src-sidebar-title{padding-top:0;}details.toggle:not(.top-doc)>summary,.impl-items>section{margin-left:10px;}.impl-items>details.toggle>summary:not(.hideme)::before,#main-content>details.toggle:not(.top-doc)>summary::before,#main-content>div>details.toggle>summary::before{left:-11px;}.impl-items>.item-info{margin-left:34px;}.src nav.sub{margin:0 0 -25px 0;padding:var(--nav-sub-mobile-padding);}}@media (min-width:701px){.scraped-example-title{position:absolute;z-index:10;background:var(--main-background-color);bottom:8px;right:5px;padding:2px 4px;box-shadow:0 0 4px var(--main-background-color);}.item-table>li>.item-name{width:33%;}.item-table>li>div{overflow-wrap:anywhere;}}@media print{nav.sidebar,nav.sub,.out-of-band,a.src,#copy-path,details.toggle[open] >summary::before,details.toggle>summary::before,details.toggle.top-doc>summary{display:none;}.docblock{margin-left:0;}main{padding:10px;}}@media (max-width:464px){.docblock{margin-left:12px;}.docblock code{overflow-wrap:break-word;overflow-wrap:anywhere;}nav.sub{flex-direction:column;}.search-form{align-self:stretch;}}.variant,.implementors-toggle>summary,.impl,#implementors-list>.docblock,.impl-items>section,.impl-items>.toggle>summary,.methods>section,.methods>.toggle>summary{margin-bottom:0.75em;}.variants>.docblock,.implementors-toggle>.docblock,.impl-items>.toggle[open]:not(:last-child),.methods>.toggle[open]:not(:last-child),.implementors-toggle[open]:not(:last-child){margin-bottom:2em;}#trait-implementations-list .impl-items>.toggle:not(:last-child),#synthetic-implementations-list .impl-items>.toggle:not(:last-child),#blanket-implementations-list .impl-items>.toggle:not(:last-child){margin-bottom:1em;}.scraped-example-list .scrape-help{margin-left:10px;padding:0 4px;font-weight:normal;font-size:12px;position:relative;bottom:1px;border:1px solid var(--scrape-example-help-border-color);border-radius:50px;color:var(--scrape-example-help-color);}.scraped-example-list .scrape-help:hover{border-color:var(--scrape-example-help-hover-border-color);color:var(--scrape-example-help-hover-color);}.scraped-example:not(.expanded) .example-wrap::before,.scraped-example:not(.expanded) .example-wrap::after{content:" ";width:100%;height:5px;position:absolute;z-index:1;}.scraped-example:not(.expanded) .example-wrap::before{top:0;background:linear-gradient(to bottom,var(--scrape-example-code-wrapper-background-start),var(--scrape-example-code-wrapper-background-end));}.scraped-example:not(.expanded) .example-wrap::after{bottom:0;background:linear-gradient(to top,var(--scrape-example-code-wrapper-background-start),var(--scrape-example-code-wrapper-background-end));}.scraped-example:not(.expanded){width:100%;overflow-y:hidden;margin-bottom:0;}.scraped-example:not(.expanded){overflow-x:hidden;}.scraped-example .rust span.highlight{background:var(--scrape-example-code-line-highlight);}.scraped-example .rust span.highlight.focus{background:var(--scrape-example-code-line-highlight-focus);}.more-examples-toggle{max-width:calc(100% + 25px);margin-top:10px;margin-left:-25px;}.more-examples-toggle .hide-more{margin-left:25px;cursor:pointer;}.more-scraped-examples{margin-left:25px;position:relative;}.toggle-line{position:absolute;top:5px;bottom:0;right:calc(100% + 10px);padding:0 4px;cursor:pointer;}.toggle-line-inner{min-width:2px;height:100%;background:var(--scrape-example-toggle-line-background);}.toggle-line:hover .toggle-line-inner{background:var(--scrape-example-toggle-line-hover-background);}.more-scraped-examples .scraped-example,.example-links{margin-top:20px;}.more-scraped-examples .scraped-example:first-child{margin-top:5px;}.example-links ul{margin-bottom:0;}:root[data-theme="light"],:root:not([data-theme]){--main-background-color:white;--main-color:black;--settings-input-color:#2196f3;--settings-input-border-color:#717171;--settings-button-color:#000;--settings-button-border-focus:#717171;--sidebar-background-color:#f5f5f5;--sidebar-background-color-hover:#e0e0e0;--code-block-background-color:#f5f5f5;--scrollbar-track-background-color:#dcdcdc;--scrollbar-thumb-background-color:rgba(36,37,39,0.6);--scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;--headings-border-bottom-color:#ddd;--border-color:#e0e0e0;--button-background-color:#fff;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:none;--mobile-sidebar-menu-filter:none;--search-input-focused-border-color:#66afe9;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(35%);--code-example-button-color:#7f7f7f;--code-example-button-hover-color:#595959;--settings-menu-filter:invert(50%);--settings-menu-hover-filter:invert(35%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ad378a;--trait-link-color:#6e4fc9;--assoc-item-link-color:#3873ad;--function-link-color:#ad7c37;--macro-link-color:#068000;--keyword-link-color:#3873ad;--mod-link-color:#3873ad;--link-color:#3873ad;--sidebar-link-color:#356da4;--sidebar-current-link-background-color:#fff;--search-result-link-focus-background-color:#ccc;--search-result-border-color:#aaa3;--search-color:#000;--search-error-code-background-color:#d0cccc;--search-results-alias-color:#000;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#e6e6e6;--search-tab-button-not-selected-background:#e6e6e6;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#fff;--stab-background-color:#fff5d6;--stab-code-color:#000;--code-highlight-kw-color:#8959a8;--code-highlight-kw-2-color:#4271ae;--code-highlight-lifetime-color:#b76514;--code-highlight-prelude-color:#4271ae;--code-highlight-prelude-val-color:#c82829;--code-highlight-number-color:#718c00;--code-highlight-string-color:#718c00;--code-highlight-literal-color:#c82829;--code-highlight-attribute-color:#c82829;--code-highlight-self-color:#c82829;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8e908c;--code-highlight-doc-comment-color:#4d4d4c;--src-line-numbers-span-color:#c67e2d;--src-line-number-highlighted-background-color:#fdffd3;--target-background-color:#fdffd3;--target-border-color:#ad7c37;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:initial;--crate-search-div-filter:invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);--crate-search-div-hover-filter:invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);--crate-search-hover-border:#717171;--src-sidebar-background-selected:#fff;--src-sidebar-background-hover:#e0e0e0;--table-alt-row-background-color:#f5f5f5;--codeblock-link-background:#eee;--scrape-example-toggle-line-background:#ccc;--scrape-example-toggle-line-hover-background:#999;--scrape-example-code-line-highlight:#fcffd6;--scrape-example-code-line-highlight-focus:#f6fdb0;--scrape-example-help-border-color:#555;--scrape-example-help-color:#333;--scrape-example-help-hover-border-color:#000;--scrape-example-help-hover-color:#000;--scrape-example-code-wrapper-background-start:rgba(255,255,255,1);--scrape-example-code-wrapper-background-end:rgba(255,255,255,0);--sidebar-resizer-hover:hsl(207,90%,66%);--sidebar-resizer-active:hsl(207,90%,54%);}:root[data-theme="dark"]{--main-background-color:#353535;--main-color:#ddd;--settings-input-color:#2196f3;--settings-input-border-color:#999;--settings-button-color:#000;--settings-button-border-focus:#ffb900;--sidebar-background-color:#505050;--sidebar-background-color-hover:#676767;--code-block-background-color:#2A2A2A;--scrollbar-track-background-color:#717171;--scrollbar-thumb-background-color:rgba(32,34,37,.6);--scrollbar-color:rgba(32,34,37,.6) #5a5a5a;--headings-border-bottom-color:#d2d2d2;--border-color:#e0e0e0;--button-background-color:#f0f0f0;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#008dfd;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(65%);--code-example-button-color:#7f7f7f;--code-example-button-hover-color:#a5a5a5;--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#2dbfb8;--trait-link-color:#b78cf2;--assoc-item-link-color:#d2991d;--function-link-color:#2bab63;--macro-link-color:#09bd00;--keyword-link-color:#d2991d;--mod-link-color:#d2991d;--link-color:#d2991d;--sidebar-link-color:#fdbf35;--sidebar-current-link-background-color:#444;--search-result-link-focus-background-color:#616161;--search-result-border-color:#aaa3;--search-color:#111;--search-error-code-background-color:#484848;--search-results-alias-color:#fff;--search-results-grey-color:#ccc;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#252525;--search-tab-button-not-selected-background:#252525;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#353535;--settings-menu-filter:invert(50%);--settings-menu-hover-filter:invert(65%);--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ab8ac1;--code-highlight-kw-2-color:#769acb;--code-highlight-lifetime-color:#d97f26;--code-highlight-prelude-color:#769acb;--code-highlight-prelude-val-color:#ee6868;--code-highlight-number-color:#83a300;--code-highlight-string-color:#83a300;--code-highlight-literal-color:#ee6868;--code-highlight-attribute-color:#ee6868;--code-highlight-self-color:#ee6868;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8d8d8b;--code-highlight-doc-comment-color:#8ca375;--src-line-numbers-span-color:#3b91e2;--src-line-number-highlighted-background-color:#0a042f;--target-background-color:#494a3d;--target-border-color:#bb7410;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);--crate-search-div-hover-filter:invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);--crate-search-hover-border:#2196f3;--src-sidebar-background-selected:#333;--src-sidebar-background-hover:#444;--table-alt-row-background-color:#2a2a2a;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(53,53,53,1);--scrape-example-code-wrapper-background-end:rgba(53,53,53,0);--sidebar-resizer-hover:hsl(207,30%,54%);--sidebar-resizer-active:hsl(207,90%,54%);}:root[data-theme="ayu"]{--main-background-color:#0f1419;--main-color:#c5c5c5;--settings-input-color:#ffb454;--settings-input-border-color:#999;--settings-button-color:#fff;--settings-button-border-focus:#e0e0e0;--sidebar-background-color:#14191f;--sidebar-background-color-hover:rgba(70,70,70,0.33);--code-block-background-color:#191f26;--scrollbar-track-background-color:transparent;--scrollbar-thumb-background-color:#5c6773;--scrollbar-color:#5c6773 #24292f;--headings-border-bottom-color:#5c6773;--border-color:#5c6773;--button-background-color:#141920;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#5c6773;--copy-path-button-color:#fff;--copy-path-img-filter:invert(70%);--copy-path-img-hover-filter:invert(100%);--code-example-button-color:#b2b2b2;--code-example-button-hover-color:#fff;--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ffa0a5;--trait-link-color:#39afd7;--assoc-item-link-color:#39afd7;--function-link-color:#fdd687;--macro-link-color:#a37acc;--keyword-link-color:#39afd7;--mod-link-color:#39afd7;--link-color:#39afd7;--sidebar-link-color:#53b1db;--sidebar-current-link-background-color:transparent;--search-result-link-focus-background-color:#3c3c3c;--search-result-border-color:#aaa3;--search-color:#fff;--search-error-code-background-color:#4f4c4c;--search-results-alias-color:#c5c5c5;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:none;--search-tab-button-not-selected-background:transparent !important;--search-tab-button-selected-border-top-color:none;--search-tab-button-selected-background:#141920 !important;--settings-menu-filter:invert(70%);--settings-menu-hover-filter:invert(100%);--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ff7733;--code-highlight-kw-2-color:#ff7733;--code-highlight-lifetime-color:#ff7733;--code-highlight-prelude-color:#69f2df;--code-highlight-prelude-val-color:#ff7733;--code-highlight-number-color:#b8cc52;--code-highlight-string-color:#b8cc52;--code-highlight-literal-color:#ff7733;--code-highlight-attribute-color:#e6e1cf;--code-highlight-self-color:#36a3d9;--code-highlight-macro-color:#a37acc;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#788797;--code-highlight-doc-comment-color:#a1ac88;--src-line-numbers-span-color:#5c6773;--src-line-number-highlighted-background-color:rgba(255,236,164,0.06);--target-background-color:rgba(255,236,164,0.06);--target-border-color:rgba(255,180,76,0.85);--kbd-color:#c5c5c5;--kbd-background:#314559;--kbd-box-shadow-color:#5c6773;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(41%) sepia(12%) saturate(487%) hue-rotate(171deg) brightness(94%) contrast(94%);--crate-search-div-hover-filter:invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg) brightness(113%) contrast(76%);--crate-search-hover-border:#e0e0e0;--src-sidebar-background-selected:#14191f;--src-sidebar-background-hover:#14191f;--table-alt-row-background-color:#191f26;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(15,20,25,1);--scrape-example-code-wrapper-background-end:rgba(15,20,25,0);--sidebar-resizer-hover:hsl(34,50%,33%);--sidebar-resizer-active:hsl(34,100%,66%);}:root[data-theme="ayu"] h1,:root[data-theme="ayu"] h2,:root[data-theme="ayu"] h3,:root[data-theme="ayu"] h4,:where(:root[data-theme="ayu"]) h1 a,:root[data-theme="ayu"] .sidebar h2 a,:root[data-theme="ayu"] .sidebar h3 a{color:#fff;}:root[data-theme="ayu"] .docblock code{color:#ffb454;}:root[data-theme="ayu"] .docblock a>code{color:#39AFD7 !important;}:root[data-theme="ayu"] .code-header,:root[data-theme="ayu"] .docblock pre>code,:root[data-theme="ayu"] pre,:root[data-theme="ayu"] pre>code,:root[data-theme="ayu"] .item-info code,:root[data-theme="ayu"] .rustdoc.source .example-wrap{color:#e6e1cf;}:root[data-theme="ayu"] .sidebar .current,:root[data-theme="ayu"] .sidebar .current a,:root[data-theme="ayu"] .sidebar a:hover,:root[data-theme="ayu"] #src-sidebar div.files>a:hover,:root[data-theme="ayu"] details.dir-entry summary:hover,:root[data-theme="ayu"] #src-sidebar div.files>a:focus,:root[data-theme="ayu"] details.dir-entry summary:focus,:root[data-theme="ayu"] #src-sidebar div.files>a.selected{color:#ffb44c;}:root[data-theme="ayu"] .sidebar-elems .location{color:#ff7733;}:root[data-theme="ayu"] .src-line-numbers .line-highlighted{color:#708090;padding-right:7px;border-right:1px solid #ffb44c;}:root[data-theme="ayu"] .search-results a:hover,:root[data-theme="ayu"] .search-results a:focus{color:#fff !important;background-color:#3c3c3c;}:root[data-theme="ayu"] .search-results a{color:#0096cf;}:root[data-theme="ayu"] .search-results a div.desc{color:#c5c5c5;}:root[data-theme="ayu"] .result-name .primitive>i,:root[data-theme="ayu"] .result-name .keyword>i{color:#788797;}:root[data-theme="ayu"] #search-tabs>button.selected{border-bottom:1px solid #ffb44c !important;border-top:none;}:root[data-theme="ayu"] #search-tabs>button:not(.selected){border:none;background-color:transparent !important;}:root[data-theme="ayu"] #search-tabs>button:hover{border-bottom:1px solid rgba(242,151,24,0.3);}:root[data-theme="ayu"] #settings-menu>a img,:root[data-theme="ayu"] #sidebar-button>a:before{filter:invert(100);} \ No newline at end of file diff --git a/static.files/scrape-examples-46fc985aa763a438.js b/static.files/scrape-examples-46fc985aa763a438.js new file mode 100644 index 0000000..87b6065 --- /dev/null +++ b/static.files/scrape-examples-46fc985aa763a438.js @@ -0,0 +1 @@ +"use strict";(function(){const DEFAULT_MAX_LINES=5;const HIDDEN_MAX_LINES=10;function scrollToLoc(elt,loc,isHidden){const lines=elt.querySelector(".src-line-numbers > pre");let scrollOffset;const maxLines=isHidden?HIDDEN_MAX_LINES:DEFAULT_MAX_LINES;if(loc[1]-loc[0]>maxLines){const line=Math.max(0,loc[0]-1);scrollOffset=lines.children[line].offsetTop}else{const halfHeight=elt.offsetHeight/2;const offsetTop=lines.children[loc[0]].offsetTop;const lastLine=lines.children[loc[1]];const offsetBot=lastLine.offsetTop+lastLine.offsetHeight;const offsetMid=(offsetTop+offsetBot)/2;scrollOffset=offsetMid-halfHeight}lines.parentElement.scrollTo(0,scrollOffset);elt.querySelector(".rust").scrollTo(0,scrollOffset)}function createScrapeButton(parent,className,content){const button=document.createElement("button");button.className=className;button.innerText=content;parent.insertBefore(button,parent.firstChild);return button}window.updateScrapedExample=(example,buttonHolder)=>{let locIndex=0;const highlights=Array.prototype.slice.call(example.querySelectorAll(".highlight"));const link=example.querySelector(".scraped-example-title a");let expandButton=null;if(!example.classList.contains("expanded")){expandButton=createScrapeButton(buttonHolder,"expand","↕")}const isHidden=example.parentElement.classList.contains("more-scraped-examples");const locs=example.locs;if(locs.length>1){const next=createScrapeButton(buttonHolder,"next","≻");const prev=createScrapeButton(buttonHolder,"prev","≺");const onChangeLoc=changeIndex=>{removeClass(highlights[locIndex],"focus");changeIndex();scrollToLoc(example,locs[locIndex][0],isHidden);addClass(highlights[locIndex],"focus");const url=locs[locIndex][1];const title=locs[locIndex][2];link.href=url;link.innerHTML=title};prev.addEventListener("click",()=>{onChangeLoc(()=>{locIndex=(locIndex-1+locs.length)%locs.length})});next.addEventListener("click",()=>{onChangeLoc(()=>{locIndex=(locIndex+1)%locs.length})})}if(expandButton){expandButton.addEventListener("click",()=>{if(hasClass(example,"expanded")){removeClass(example,"expanded");scrollToLoc(example,locs[0][0],isHidden)}else{addClass(example,"expanded")}})}};function setupLoc(example,isHidden){example.locs=JSON.parse(example.attributes.getNamedItem("data-locs").textContent);scrollToLoc(example,example.locs[0][0],isHidden)}const firstExamples=document.querySelectorAll(".scraped-example-list > .scraped-example");onEachLazy(firstExamples,el=>setupLoc(el,false));onEachLazy(document.querySelectorAll(".more-examples-toggle"),toggle=>{onEachLazy(toggle.querySelectorAll(".toggle-line, .hide-more"),button=>{button.addEventListener("click",()=>{toggle.open=false})});const moreExamples=toggle.querySelectorAll(".scraped-example");toggle.querySelector("summary").addEventListener("click",()=>{setTimeout(()=>{onEachLazy(moreExamples,el=>setupLoc(el,true))})},{once:true})})})() \ No newline at end of file diff --git a/static.files/search-f0d225181b97f9a4.js b/static.files/search-f0d225181b97f9a4.js new file mode 100644 index 0000000..d34fb34 --- /dev/null +++ b/static.files/search-f0d225181b97f9a4.js @@ -0,0 +1,6 @@ +"use strict";if(!Array.prototype.toSpliced){Array.prototype.toSpliced=function(){const me=this.slice();Array.prototype.splice.apply(me,arguments);return me}}(function(){const itemTypes=["keyword","primitive","mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","associatedtype","constant","associatedconstant","union","foreigntype","existential","attr","derive","traitalias","generic",];const TY_GENERIC=itemTypes.indexOf("generic");const TY_IMPORT=itemTypes.indexOf("import");const ROOT_PATH=typeof window!=="undefined"?window.rootPath:"../";const UNBOXING_LIMIT=5;const REGEX_IDENT=/\p{ID_Start}\p{ID_Continue}*|_\p{ID_Continue}+/uy;const REGEX_INVALID_TYPE_FILTER=/[^a-z]/ui;const MAX_RESULTS=200;const NO_TYPE_FILTER=-1;const editDistanceState={current:[],prev:[],prevPrev:[],calculate:function calculate(a,b,limit){if(a.lengthlimit){return limit+1}while(b.length>0&&b[0]===a[0]){a=a.substring(1);b=b.substring(1)}while(b.length>0&&b[b.length-1]===a[a.length-1]){a=a.substring(0,a.length-1);b=b.substring(0,b.length-1)}if(b.length===0){return minDist}const aLength=a.length;const bLength=b.length;for(let i=0;i<=bLength;++i){this.current[i]=0;this.prev[i]=i;this.prevPrev[i]=Number.MAX_VALUE}for(let i=1;i<=aLength;++i){this.current[0]=i;const aIdx=i-1;for(let j=1;j<=bLength;++j){const bIdx=j-1;const substitutionCost=a[aIdx]===b[bIdx]?0:1;this.current[j]=Math.min(this.prev[j]+1,this.current[j-1]+1,this.prev[j-1]+substitutionCost,);if((i>1)&&(j>1)&&(a[aIdx]===b[bIdx-1])&&(a[aIdx-1]===b[bIdx])){this.current[j]=Math.min(this.current[j],this.prevPrev[j-2]+1,)}}const prevPrevTmp=this.prevPrev;this.prevPrev=this.prev;this.prev=this.current;this.current=prevPrevTmp}const distance=this.prev[bLength];return distance<=limit?distance:(limit+1)},};function editDistance(a,b,limit){return editDistanceState.calculate(a,b,limit)}function isEndCharacter(c){return"=,>-])".indexOf(c)!==-1}function isSeparatorCharacter(c){return c===","||c==="="}function isReturnArrow(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="->"}function skipWhitespace(parserState){while(parserState.pos0){const c=parserState.userQuery[pos-1];if(c===lookingFor){return true}else if(c!==" "){break}pos-=1}return false}function isLastElemGeneric(elems,parserState){return(elems.length>0&&elems[elems.length-1].generics.length>0)||prevIs(parserState,">")}function getFilteredNextElem(query,parserState,elems,isInGenerics){const start=parserState.pos;if(parserState.userQuery[parserState.pos]===":"&&!isPathStart(parserState)){throw["Expected type filter before ",":"]}getNextElem(query,parserState,elems,isInGenerics);if(parserState.userQuery[parserState.pos]===":"&&!isPathStart(parserState)){if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter ",parserState.typeFilter+":",")",]}if(elems.length===0){throw["Expected type filter before ",":"]}else if(query.literalSearch){throw["Cannot use quotes on type filter"]}const typeFilterElem=elems.pop();checkExtraTypeFilterCharacters(start,parserState);parserState.typeFilter=typeFilterElem.name;parserState.pos+=1;parserState.totalElems-=1;query.literalSearch=false;getNextElem(query,parserState,elems,isInGenerics)}}function getItemsBefore(query,parserState,elems,endChar){let foundStopChar=true;let foundSeparator=false;const oldTypeFilter=parserState.typeFilter;parserState.typeFilter=null;const oldIsInBinding=parserState.isInBinding;parserState.isInBinding=null;let hofParameters=null;let extra="";if(endChar===">"){extra="<"}else if(endChar==="]"){extra="["}else if(endChar===")"){extra="("}else if(endChar===""){extra="->"}else{extra=endChar}while(parserState.pos"," after ","="]}hofParameters=[...elems];elems.length=0;parserState.pos+=2;foundStopChar=true;foundSeparator=false;continue}else if(c===" "){parserState.pos+=1;continue}else if(isSeparatorCharacter(c)){parserState.pos+=1;foundStopChar=true;foundSeparator=true;continue}else if(c===":"&&isPathStart(parserState)){throw["Unexpected ","::",": paths cannot start with ","::"]}else if(isEndCharacter(c)){throw["Unexpected ",c," after ",extra]}if(!foundStopChar){let extra=[];if(isLastElemGeneric(query.elems,parserState)){extra=[" after ",">"]}else if(prevIs(parserState,"\"")){throw["Cannot have more than one element if you use quotes"]}if(endChar!==""){throw["Expected ",",",", ","=",", or ",endChar,...extra,", found ",c,]}throw["Expected ",","," or ","=",...extra,", found ",c,]}const posBefore=parserState.pos;getFilteredNextElem(query,parserState,elems,endChar!=="");if(endChar!==""&&parserState.pos>=parserState.length){throw["Unclosed ",extra]}if(posBefore===parserState.pos){parserState.pos+=1}foundStopChar=false}if(parserState.pos>=parserState.length&&endChar!==""){throw["Unclosed ",extra]}parserState.pos+=1;if(hofParameters){foundSeparator=false;if([...elems,...hofParameters].some(x=>x.bindingName)||parserState.isInBinding){throw["Unexpected ","="," within ","->"]}const hofElem=makePrimitiveElement("->",{generics:hofParameters,bindings:new Map([["output",[...elems]]]),typeFilter:null,});elems.length=0;elems[0]=hofElem}parserState.typeFilter=oldTypeFilter;parserState.isInBinding=oldIsInBinding;return{foundSeparator}}function getNextElem(query,parserState,elems,isInGenerics){const generics=[];skipWhitespace(parserState);let start=parserState.pos;let end;if("[(".indexOf(parserState.userQuery[parserState.pos])!==-1){let endChar=")";let name="()";let friendlyName="tuple";if(parserState.userQuery[parserState.pos]==="["){endChar="]";name="[]";friendlyName="slice"}parserState.pos+=1;const{foundSeparator}=getItemsBefore(query,parserState,generics,endChar);const typeFilter=parserState.typeFilter;const bindingName=parserState.isInBinding;parserState.typeFilter=null;parserState.isInBinding=null;for(const gen of generics){if(gen.bindingName!==null){throw["Type parameter ","=",` cannot be within ${friendlyName} `,name]}}if(name==="()"&&!foundSeparator&&generics.length===1&&typeFilter===null){elems.push(generics[0])}else if(name==="()"&&generics.length===1&&generics[0].name==="->"){generics[0].typeFilter=typeFilter;elems.push(generics[0])}else{if(typeFilter!==null&&typeFilter!=="primitive"){throw["Invalid search type: primitive ",name," and ",typeFilter," both specified",]}parserState.totalElems+=1;if(isInGenerics){parserState.genericsElems+=1}elems.push(makePrimitiveElement(name,{bindingName,generics}))}}else if(parserState.userQuery[parserState.pos]==="&"){if(parserState.typeFilter!==null&&parserState.typeFilter!=="primitive"){throw["Invalid search type: primitive ","&"," and ",parserState.typeFilter," both specified",]}parserState.typeFilter=null;parserState.pos+=1;let c=parserState.userQuery[parserState.pos];while(c===" "&&parserState.pos=end){throw["Found generics without a path"]}parserState.pos+=1;getItemsBefore(query,parserState,generics,">")}else if(parserState.pos=end){throw["Found generics without a path"]}if(parserState.isInBinding){throw["Unexpected ","("," after ","="]}parserState.pos+=1;const typeFilter=parserState.typeFilter;parserState.typeFilter=null;getItemsBefore(query,parserState,generics,")");skipWhitespace(parserState);if(isReturnArrow(parserState)){parserState.pos+=2;skipWhitespace(parserState);getFilteredNextElem(query,parserState,generics,isInGenerics);generics[generics.length-1].bindingName=makePrimitiveElement("output")}else{generics.push(makePrimitiveElement(null,{bindingName:makePrimitiveElement("output"),typeFilter:null,}))}parserState.typeFilter=typeFilter}if(isStringElem){skipWhitespace(parserState)}if(start>=end&&generics.length===0){return}if(parserState.userQuery[parserState.pos]==="="){if(parserState.isInBinding){throw["Cannot write ","="," twice in a binding"]}if(!isInGenerics){throw["Type parameter ","="," must be within generics list"]}const name=parserState.userQuery.slice(start,end).trim();if(name==="!"){throw["Type parameter ","="," key cannot be ","!"," never type"]}if(name.includes("!")){throw["Type parameter ","="," key cannot be ","!"," macro"]}if(name.includes("::")){throw["Type parameter ","="," key cannot contain ","::"," path"]}if(name.includes(":")){throw["Type parameter ","="," key cannot contain ",":"," type"]}parserState.isInBinding={name,generics}}else{elems.push(createQueryElement(query,parserState,parserState.userQuery.slice(start,end),generics,isInGenerics,),)}}}function checkExtraTypeFilterCharacters(start,parserState){const query=parserState.userQuery.slice(start,parserState.pos).trim();const match=query.match(REGEX_INVALID_TYPE_FILTER);if(match){throw["Unexpected ",match[0]," in type filter (before ",":",")",]}}function createQueryElement(query,parserState,name,generics,isInGenerics){const path=name.trim();if(path.length===0&&generics.length===0){throw["Unexpected ",parserState.userQuery[parserState.pos]]}if(query.literalSearch&&parserState.totalElems-parserState.genericsElems>0){throw["Cannot have more than one element if you use quotes"]}const typeFilter=parserState.typeFilter;parserState.typeFilter=null;if(name.trim()==="!"){if(typeFilter!==null&&typeFilter!=="primitive"){throw["Invalid search type: primitive never type ","!"," and ",typeFilter," both specified",]}if(generics.length!==0){throw["Never type ","!"," does not accept generic parameters",]}const bindingName=parserState.isInBinding;parserState.isInBinding=null;return makePrimitiveElement("never",{bindingName})}const quadcolon=/::\s*::/.exec(path);if(path.startsWith("::")){throw["Paths cannot start with ","::"]}else if(path.endsWith("::")){throw["Paths cannot end with ","::"]}else if(quadcolon!==null){throw["Unexpected ",quadcolon[0]]}const pathSegments=path.split(/(?:::\s*)|(?:\s+(?:::\s*)?)/);if(pathSegments.length===0||(pathSegments.length===1&&pathSegments[0]==="")){if(generics.length>0||prevIs(parserState,">")){throw["Found generics without a path"]}else{throw["Unexpected ",parserState.userQuery[parserState.pos]]}}for(const[i,pathSegment]of pathSegments.entries()){if(pathSegment==="!"){if(i!==0){throw["Never type ","!"," is not associated item"]}pathSegments[i]="never"}}parserState.totalElems+=1;if(isInGenerics){parserState.genericsElems+=1}const bindingName=parserState.isInBinding;parserState.isInBinding=null;const bindings=new Map();const pathLast=pathSegments[pathSegments.length-1];return{name:name.trim(),id:null,fullPath:pathSegments,pathWithoutLast:pathSegments.slice(0,pathSegments.length-1),pathLast,normalizedPathLast:pathLast.replace(/_/g,""),generics:generics.filter(gen=>{if(gen.bindingName!==null){if(gen.name!==null){gen.bindingName.generics.unshift(gen)}bindings.set(gen.bindingName.name,gen.bindingName.generics);return false}return true}),bindings,typeFilter,bindingName,}}function makePrimitiveElement(name,extra){return Object.assign({name,id:null,fullPath:[name],pathWithoutLast:[],pathLast:name,normalizedPathLast:name,generics:[],bindings:new Map(),typeFilter:"primitive",bindingName:null,},extra)}function getStringElem(query,parserState,isInGenerics){if(isInGenerics){throw["Unexpected ","\""," in generics"]}else if(query.literalSearch){throw["Cannot have more than one literal search element"]}else if(parserState.totalElems-parserState.genericsElems>0){throw["Cannot use literal search when there is more than one element"]}parserState.pos+=1;const start=parserState.pos;const end=getIdentEndPosition(parserState);if(parserState.pos>=parserState.length){throw["Unclosed ","\""]}else if(parserState.userQuery[end]!=="\""){throw["Unexpected ",parserState.userQuery[end]," in a string element"]}else if(start===end){throw["Cannot have empty string element"]}parserState.pos+=1;query.literalSearch=true}function getIdentEndPosition(parserState){let afterIdent=consumeIdent(parserState);let end=parserState.pos;let macroExclamation=-1;while(parserState.pos0){throw["Unexpected ",c," after ",parserState.userQuery[parserState.pos-1]," (not a valid identifier)"]}else{throw["Unexpected ",c," (not a valid identifier)"]}parserState.pos+=1;afterIdent=consumeIdent(parserState);end=parserState.pos}if(macroExclamation!==-1){if(parserState.typeFilter===null){parserState.typeFilter="macro"}else if(parserState.typeFilter!=="macro"){throw["Invalid search type: macro ","!"," and ",parserState.typeFilter," both specified",]}end=macroExclamation}return end}function isSpecialStartCharacter(c){return"<\"".indexOf(c)!==-1}function isPathStart(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="::"}function consumeIdent(parserState){REGEX_IDENT.lastIndex=parserState.pos;const match=parserState.userQuery.match(REGEX_IDENT);if(match){parserState.pos+=match[0].length;return true}return false}function isPathSeparator(c){return c===":"||c===" "}class VlqHexDecoder{constructor(string,cons){this.string=string;this.cons=cons;this.offset=0;this.backrefQueue=[]}decodeList(){let c=this.string.charCodeAt(this.offset);const ret=[];while(c!==125){ret.push(this.decode());c=this.string.charCodeAt(this.offset)}this.offset+=1;return ret}decode(){let n=0;let c=this.string.charCodeAt(this.offset);if(c===123){this.offset+=1;return this.decodeList()}while(c<96){n=(n<<4)|(c&0xF);this.offset+=1;c=this.string.charCodeAt(this.offset)}n=(n<<4)|(c&0xF);const[sign,value]=[n&1,n>>1];this.offset+=1;return sign?-value:value}next(){const c=this.string.charCodeAt(this.offset);if(c>=48&&c<64){this.offset+=1;return this.backrefQueue[c-48]}if(c===96){this.offset+=1;return this.cons(0)}const result=this.cons(this.decode());this.backrefQueue.unshift(result);if(this.backrefQueue.length>16){this.backrefQueue.pop()}return result}}class RoaringBitmap{constructor(str){const strdecoded=atob(str);const u8array=new Uint8Array(strdecoded.length);for(let j=0;j=4){offsets=[];for(let j=0;j>3]&(1<<(j&0x7))){const runcount=(u8array[i]|(u8array[i+1]<<8));i+=2;this.containers.push(new RoaringBitmapRun(runcount,u8array.slice(i,i+(runcount*4)),));i+=runcount*4}else if(this.cardinalities[j]>=4096){this.containers.push(new RoaringBitmapBits(u8array.slice(i,i+8192)));i+=8192}else{const end=this.cardinalities[j]*2;this.containers.push(new RoaringBitmapArray(this.cardinalities[j],u8array.slice(i,i+end),));i+=end}}}contains(keyvalue){const key=keyvalue>>16;const value=keyvalue&0xFFFF;for(let i=0;i=start&&value<=(start+lenm1)){return true}}return false}}class RoaringBitmapArray{constructor(cardinality,array){this.cardinality=cardinality;this.array=array}contains(value){const l=this.cardinality*2;for(let i=0;i>3]&(1<<(value&7)))}}class DocSearch{constructor(rawSearchIndex,rootPath,searchState){this.searchIndexDeprecated=new Map();this.searchIndexEmptyDesc=new Map();this.functionTypeFingerprint=null;this.typeNameIdMap=new Map();this.ALIASES=new Map();this.rootPath=rootPath;this.searchState=searchState;this.typeNameIdOfArray=this.buildTypeMapIndex("array");this.typeNameIdOfSlice=this.buildTypeMapIndex("slice");this.typeNameIdOfArrayOrSlice=this.buildTypeMapIndex("[]");this.typeNameIdOfTuple=this.buildTypeMapIndex("tuple");this.typeNameIdOfUnit=this.buildTypeMapIndex("unit");this.typeNameIdOfTupleOrUnit=this.buildTypeMapIndex("()");this.typeNameIdOfFn=this.buildTypeMapIndex("fn");this.typeNameIdOfFnMut=this.buildTypeMapIndex("fnmut");this.typeNameIdOfFnOnce=this.buildTypeMapIndex("fnonce");this.typeNameIdOfHof=this.buildTypeMapIndex("->");this.EMPTY_BINDINGS_MAP=new Map();this.EMPTY_GENERICS_ARRAY=[];this.TYPES_POOL=new Map();this.searchIndex=this.buildIndex(rawSearchIndex)}buildTypeMapIndex(name,isAssocType){if(name===""||name===null){return null}if(this.typeNameIdMap.has(name)){const obj=this.typeNameIdMap.get(name);obj.assocOnly=isAssocType&&obj.assocOnly;return obj.id}else{const id=this.typeNameIdMap.size;this.typeNameIdMap.set(name,{id,assocOnly:isAssocType});return id}}buildItemSearchTypeAll(types,lowercasePaths){return types.length>0?types.map(type=>this.buildItemSearchType(type,lowercasePaths)):this.EMPTY_GENERICS_ARRAY}buildItemSearchType(type,lowercasePaths,isAssocType){const PATH_INDEX_DATA=0;const GENERICS_DATA=1;const BINDINGS_DATA=2;let pathIndex,generics,bindings;if(typeof type==="number"){pathIndex=type;generics=this.EMPTY_GENERICS_ARRAY;bindings=this.EMPTY_BINDINGS_MAP}else{pathIndex=type[PATH_INDEX_DATA];generics=this.buildItemSearchTypeAll(type[GENERICS_DATA],lowercasePaths,);if(type.length>BINDINGS_DATA&&type[BINDINGS_DATA].length>0){bindings=new Map(type[BINDINGS_DATA].map(binding=>{const[assocType,constraints]=binding;return[this.buildItemSearchType(assocType,lowercasePaths,true).id,this.buildItemSearchTypeAll(constraints,lowercasePaths),]}))}else{bindings=this.EMPTY_BINDINGS_MAP}}let result;if(pathIndex<0){result={id:pathIndex,ty:TY_GENERIC,path:null,exactPath:null,generics,bindings,}}else if(pathIndex===0){result={id:null,ty:null,path:null,exactPath:null,generics,bindings,}}else{const item=lowercasePaths[pathIndex-1];result={id:this.buildTypeMapIndex(item.name,isAssocType),ty:item.ty,path:item.path,exactPath:item.exactPath,generics,bindings,}}const cr=this.TYPES_POOL.get(result.id);if(cr){if(cr.generics.length===result.generics.length&&cr.generics!==result.generics&&cr.generics.every((x,i)=>result.generics[i]===x)){result.generics=cr.generics}if(cr.bindings.size===result.bindings.size&&cr.bindings!==result.bindings){let ok=true;for(const[k,v]of cr.bindings.entries()){const v2=result.bindings.get(v);if(!v2){ok=false;break}if(v!==v2&&v.length===v2.length&&v.every((x,i)=>v2[i]===x)){result.bindings.set(k,v)}else if(v!==v2){ok=false;break}}if(ok){result.bindings=cr.bindings}}if(cr.ty===result.ty&&cr.path===result.path&&cr.bindings===result.bindings&&cr.generics===result.generics&&cr.ty===result.ty){return cr}}this.TYPES_POOL.set(result.id,result);return result}buildFunctionTypeFingerprint(type,output,fps){let input=type.id;if(input===this.typeNameIdOfArray||input===this.typeNameIdOfSlice){input=this.typeNameIdOfArrayOrSlice}if(input===this.typeNameIdOfTuple||input===this.typeNameIdOfUnit){input=this.typeNameIdOfTupleOrUnit}if(input===this.typeNameIdOfFn||input===this.typeNameIdOfFnMut||input===this.typeNameIdOfFnOnce){input=this.typeNameIdOfHof}const hashint1=k=>{k=(~~k+0x7ed55d16)+(k<<12);k=(k ^ 0xc761c23c)^(k>>>19);k=(~~k+0x165667b1)+(k<<5);k=(~~k+0xd3a2646c)^(k<<9);k=(~~k+0xfd7046c5)+(k<<3);return(k ^ 0xb55a4f09)^(k>>>16)};const hashint2=k=>{k=~k+(k<<15);k ^=k>>>12;k+=k<<2;k ^=k>>>4;k=Math.imul(k,2057);return k ^(k>>16)};if(input!==null){const h0a=hashint1(input);const h0b=hashint2(input);const h1a=~~(h0a+Math.imul(h0b,2));const h1b=~~(h0a+Math.imul(h0b,3));const h2a=~~(h0a+Math.imul(h0b,4));const h2b=~~(h0a+Math.imul(h0b,5));output[0]|=(1<<(h0a%32))|(1<<(h1b%32));output[1]|=(1<<(h1a%32))|(1<<(h2b%32));output[2]|=(1<<(h2a%32))|(1<<(h0b%32));fps.add(input)}for(const g of type.generics){this.buildFunctionTypeFingerprint(g,output,fps)}const fb={id:null,ty:0,generics:this.EMPTY_GENERICS_ARRAY,bindings:this.EMPTY_BINDINGS_MAP,};for(const[k,v]of type.bindings.entries()){fb.id=k;fb.generics=v;this.buildFunctionTypeFingerprint(fb,output,fps)}output[3]=fps.size}buildIndex(rawSearchIndex){const buildFunctionSearchTypeCallback=lowercasePaths=>{return functionSearchType=>{if(functionSearchType===0){return null}const INPUTS_DATA=0;const OUTPUT_DATA=1;let inputs,output;if(typeof functionSearchType[INPUTS_DATA]==="number"){inputs=[this.buildItemSearchType(functionSearchType[INPUTS_DATA],lowercasePaths),]}else{inputs=this.buildItemSearchTypeAll(functionSearchType[INPUTS_DATA],lowercasePaths,)}if(functionSearchType.length>1){if(typeof functionSearchType[OUTPUT_DATA]==="number"){output=[this.buildItemSearchType(functionSearchType[OUTPUT_DATA],lowercasePaths,),]}else{output=this.buildItemSearchTypeAll(functionSearchType[OUTPUT_DATA],lowercasePaths,)}}else{output=[]}const where_clause=[];const l=functionSearchType.length;for(let i=2;inoop);let descShard={crate,shard:0,start:0,len:itemDescShardDecoder.next(),promise:null,resolve:null,};const descShardList=[descShard];this.searchIndexDeprecated.set(crate,new RoaringBitmap(crateCorpus.c));this.searchIndexEmptyDesc.set(crate,new RoaringBitmap(crateCorpus.e));let descIndex=0;const crateRow={crate,ty:3,name:crate,path:"",descShard,descIndex,exactPath:"",desc:crateCorpus.doc,parent:undefined,type:null,id,word:crate,normalizedName:crate.indexOf("_")===-1?crate:crate.replace(/_/g,""),bitIndex:0,implDisambiguator:null,};id+=1;searchIndex.push(crateRow);currentIndex+=1;if(!this.searchIndexEmptyDesc.get(crate).contains(0)){descIndex+=1}const itemTypes=crateCorpus.t;const itemNames=crateCorpus.n;const itemPaths=new Map(crateCorpus.q);const itemReexports=new Map(crateCorpus.r);const itemParentIdxDecoder=new VlqHexDecoder(crateCorpus.i,noop=>noop);const implDisambiguator=new Map(crateCorpus.b);const paths=crateCorpus.p;const aliases=crateCorpus.a;const lowercasePaths=[];const itemFunctionDecoder=new VlqHexDecoder(crateCorpus.f,buildFunctionSearchTypeCallback(lowercasePaths),);let len=paths.length;let lastPath=itemPaths.get(0);for(let i=0;i2){path=itemPaths.has(elem[2])?itemPaths.get(elem[2]):lastPath;lastPath=path}const exactPath=elem.length>3?itemPaths.get(elem[3]):path;lowercasePaths.push({ty,name:name.toLowerCase(),path,exactPath});paths[i]={ty,name,path,exactPath}}lastPath="";len=itemTypes.length;let lastName="";let lastWord="";for(let i=0;i=descShard.len&&!this.searchIndexEmptyDesc.get(crate).contains(bitIndex)){descShard={crate,shard:descShard.shard+1,start:descShard.start+descShard.len,len:itemDescShardDecoder.next(),promise:null,resolve:null,};descIndex=0;descShardList.push(descShard)}const name=itemNames[i]===""?lastName:itemNames[i];const word=itemNames[i]===""?lastWord:itemNames[i].toLowerCase();const path=itemPaths.has(i)?itemPaths.get(i):lastPath;const type=itemFunctionDecoder.next();if(type!==null){if(type){const fp=this.functionTypeFingerprint.subarray(id*4,(id+1)*4);const fps=new Set();for(const t of type.inputs){this.buildFunctionTypeFingerprint(t,fp,fps)}for(const t of type.output){this.buildFunctionTypeFingerprint(t,fp,fps)}for(const w of type.where_clause){for(const t of w){this.buildFunctionTypeFingerprint(t,fp,fps)}}}}const itemParentIdx=itemParentIdxDecoder.next();const row={crate,ty:itemTypes.charCodeAt(i)-65,name,path,descShard,descIndex,exactPath:itemReexports.has(i)?itemPaths.get(itemReexports.get(i)):path,parent:itemParentIdx>0?paths[itemParentIdx-1]:undefined,type,id,word,normalizedName:word.indexOf("_")===-1?word:word.replace(/_/g,""),bitIndex,implDisambiguator:implDisambiguator.has(i)?implDisambiguator.get(i):null,};id+=1;searchIndex.push(row);lastPath=row.path;if(!this.searchIndexEmptyDesc.get(crate).contains(bitIndex)){descIndex+=1}lastName=name;lastWord=word}if(aliases){const currentCrateAliases=new Map();this.ALIASES.set(crate,currentCrateAliases);for(const alias_name in aliases){if(!Object.prototype.hasOwnProperty.call(aliases,alias_name)){continue}let currentNameAliases;if(currentCrateAliases.has(alias_name)){currentNameAliases=currentCrateAliases.get(alias_name)}else{currentNameAliases=[];currentCrateAliases.set(alias_name,currentNameAliases)}for(const local_alias of aliases[alias_name]){currentNameAliases.push(local_alias+currentIndex)}}}currentIndex+=itemTypes.length;this.searchState.descShards.set(crate,descShardList)}this.TYPES_POOL=new Map();return searchIndex}static parseQuery(userQuery){function itemTypeFromName(typename){const index=itemTypes.findIndex(i=>i===typename);if(index<0){throw["Unknown type filter ",typename]}return index}function convertTypeFilterOnElem(elem){if(elem.typeFilter!==null){let typeFilter=elem.typeFilter;if(typeFilter==="const"){typeFilter="constant"}elem.typeFilter=itemTypeFromName(typeFilter)}else{elem.typeFilter=NO_TYPE_FILTER}for(const elem2 of elem.generics){convertTypeFilterOnElem(elem2)}for(const constraints of elem.bindings.values()){for(const constraint of constraints){convertTypeFilterOnElem(constraint)}}}function newParsedQuery(userQuery){return{original:userQuery,userQuery:userQuery.toLowerCase(),elems:[],returned:[],foundElems:0,totalElems:0,literalSearch:false,hasReturnArrow:false,error:null,correction:null,proposeCorrectionFrom:null,proposeCorrectionTo:null,typeFingerprint:new Uint32Array(4),}}function parseInput(query,parserState){let foundStopChar=true;while(parserState.pos"){if(isReturnArrow(parserState)){query.hasReturnArrow=true;break}throw["Unexpected ",c," (did you mean ","->","?)"]}else if(parserState.pos>0){throw["Unexpected ",c," after ",parserState.userQuery[parserState.pos-1]]}throw["Unexpected ",c]}else if(c===" "){skipWhitespace(parserState);continue}if(!foundStopChar){let extra="";if(isLastElemGeneric(query.elems,parserState)){extra=[" after ",">"]}else if(prevIs(parserState,"\"")){throw["Cannot have more than one element if you use quotes"]}if(parserState.typeFilter!==null){throw["Expected ",","," or ","->",...extra,", found ",c,]}throw["Expected ",",",", ",":"," or ","->",...extra,", found ",c,]}const before=query.elems.length;getFilteredNextElem(query,parserState,query.elems,false);if(query.elems.length===before){parserState.pos+=1}foundStopChar=false}if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter ",parserState.typeFilter+":",")",]}while(parserState.pos1}query.foundElems=query.elems.length+query.returned.length;query.totalElems=parserState.totalElems;return query}async execQuery(parsedQuery,filterCrates,currentCrate){const results_others=new Map(),results_in_args=new Map(),results_returned=new Map();function createQueryResults(results_in_args,results_returned,results_others,parsedQuery){return{"in_args":results_in_args,"returned":results_returned,"others":results_others,"query":parsedQuery,}}const buildHrefAndPath=item=>{let displayPath;let href;const type=itemTypes[item.ty];const name=item.name;let path=item.path;let exactPath=item.exactPath;if(type==="mod"){displayPath=path+"::";href=this.rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="import"){displayPath=item.path+"::";href=this.rootPath+item.path.replace(/::/g,"/")+"/index.html#reexport."+name}else if(type==="primitive"||type==="keyword"){displayPath="";href=this.rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=this.rootPath+name+"/index.html"}else if(item.parent!==undefined){const myparent=item.parent;let anchor=type+"."+name;const parentType=itemTypes[myparent.ty];let pageType=parentType;let pageName=myparent.name;exactPath=`${myparent.exactPath}::${myparent.name}`;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){const enumNameIdx=item.path.lastIndexOf("::");const enumName=item.path.substr(enumNameIdx+2);path=item.path.substr(0,enumNameIdx);displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}if(item.implDisambiguator!==null){anchor=item.implDisambiguator+"/"+anchor}href=this.rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html#"+anchor}else{displayPath=item.path+"::";href=this.rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href,`${exactPath}::${name}`]};function pathSplitter(path){const tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}const transformResults=results=>{const duplicates=new Set();const out=[];for(const result of results){if(result.id!==-1){const obj=this.searchIndex[result.id];obj.dist=result.dist;const res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=res[2]+"|"+obj.ty;if(duplicates.has(obj.fullPath)){continue}if(obj.ty===TY_IMPORT&&duplicates.has(res[2])){continue}if(duplicates.has(res[2]+"|"+TY_IMPORT)){continue}duplicates.add(obj.fullPath);duplicates.add(res[2]);obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}return out};const sortResults=async(results,isType,preferredCrate)=>{const userQuery=parsedQuery.userQuery;const casedUserQuery=parsedQuery.original;const isMixedCase=casedUserQuery!==userQuery;const result_list=[];for(const result of results.values()){result.item=this.searchIndex[result.id];result.word=this.searchIndex[result.id].word;result_list.push(result)}result_list.sort((aaa,bbb)=>{let a,b;if(isMixedCase){a=(aaa.item.name!==casedUserQuery);b=(bbb.item.name!==casedUserQuery);if(a!==b){return a-b}}a=(aaa.word!==userQuery);b=(bbb.word!==userQuery);if(a!==b){return a-b}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.path_dist;b=bbb.path_dist;if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}a=(aaa.dist);b=(bbb.dist);if(a!==b){return a-b}a=this.searchIndexDeprecated.get(aaa.item.crate).contains(aaa.item.bitIndex);b=this.searchIndexDeprecated.get(bbb.item.crate).contains(bbb.item.bitIndex);if(a!==b){return a-b}a=(aaa.item.crate!==preferredCrate);b=(bbb.item.crate!==preferredCrate);if(a!==b){return a-b}a=aaa.word.length;b=bbb.word.length;if(a!==b){return a-b}a=aaa.word;b=bbb.word;if(a!==b){return(a>b?+1:-1)}a=this.searchIndexEmptyDesc.get(aaa.item.crate).contains(aaa.item.bitIndex);b=this.searchIndexEmptyDesc.get(bbb.item.crate).contains(bbb.item.bitIndex);if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});return transformResults(result_list)};function unifyFunctionTypes(fnTypesIn,queryElems,whereClause,mgensIn,solutionCb,unboxingDepth,){if(unboxingDepth>=UNBOXING_LIMIT){return false}const mgens=mgensIn===null?null:new Map(mgensIn);if(queryElems.length===0){return!solutionCb||solutionCb(mgens)}if(!fnTypesIn||fnTypesIn.length===0){return false}const ql=queryElems.length;const fl=fnTypesIn.length;if(ql===1&&queryElems[0].generics.length===0&&queryElems[0].bindings.size===0){const queryElem=queryElems[0];for(const fnType of fnTypesIn){if(!unifyFunctionTypeIsMatchCandidate(fnType,queryElem,mgens)){continue}if(fnType.id<0&&queryElem.id<0){if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==queryElem.id){continue}const mgensScratch=new Map(mgens);mgensScratch.set(fnType.id,queryElem.id);if(!solutionCb||solutionCb(mgensScratch)){return true}}else if(!solutionCb||solutionCb(mgens?new Map(mgens):null)){return true}}for(const fnType of fnTypesIn){if(!unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth+1,)){continue}if(fnType.id<0){if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==0){continue}const mgensScratch=new Map(mgens);mgensScratch.set(fnType.id,0);if(unifyFunctionTypes(whereClause[(-fnType.id)-1],queryElems,whereClause,mgensScratch,solutionCb,unboxingDepth+1,)){return true}}else if(unifyFunctionTypes([...fnType.generics,...Array.from(fnType.bindings.values()).flat()],queryElems,whereClause,mgens?new Map(mgens):null,solutionCb,unboxingDepth+1,)){return true}}return false}const fnTypes=fnTypesIn.slice();const flast=fl-1;const qlast=ql-1;const queryElem=queryElems[qlast];let queryElemsTmp=null;for(let i=flast;i>=0;i-=1){const fnType=fnTypes[i];if(!unifyFunctionTypeIsMatchCandidate(fnType,queryElem,mgens)){continue}let mgensScratch;if(fnType.id<0){mgensScratch=new Map(mgens);if(mgensScratch.has(fnType.id)&&mgensScratch.get(fnType.id)!==queryElem.id){continue}mgensScratch.set(fnType.id,queryElem.id)}else{mgensScratch=mgens}fnTypes[i]=fnTypes[flast];fnTypes.length=flast;if(!queryElemsTmp){queryElemsTmp=queryElems.slice(0,qlast)}const passesUnification=unifyFunctionTypes(fnTypes,queryElemsTmp,whereClause,mgensScratch,mgensScratch=>{if(fnType.generics.length===0&&queryElem.generics.length===0&&fnType.bindings.size===0&&queryElem.bindings.size===0){return!solutionCb||solutionCb(mgensScratch)}const solution=unifyFunctionTypeCheckBindings(fnType,queryElem,whereClause,mgensScratch,unboxingDepth,);if(!solution){return false}const simplifiedGenerics=solution.simplifiedGenerics;for(const simplifiedMgens of solution.mgens){const passesUnification=unifyFunctionTypes(simplifiedGenerics,queryElem.generics,whereClause,simplifiedMgens,solutionCb,unboxingDepth,);if(passesUnification){return true}}return false},unboxingDepth,);if(passesUnification){return true}fnTypes[flast]=fnTypes[i];fnTypes[i]=fnType;fnTypes.length=fl}for(let i=flast;i>=0;i-=1){const fnType=fnTypes[i];if(!unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth+1,)){continue}let mgensScratch;if(fnType.id<0){mgensScratch=new Map(mgens);if(mgensScratch.has(fnType.id)&&mgensScratch.get(fnType.id)!==0){continue}mgensScratch.set(fnType.id,0)}else{mgensScratch=mgens}const generics=fnType.id<0?whereClause[(-fnType.id)-1]:fnType.generics;const bindings=fnType.bindings?Array.from(fnType.bindings.values()).flat():[];const passesUnification=unifyFunctionTypes(fnTypes.toSpliced(i,1,...generics,...bindings),queryElems,whereClause,mgensScratch,solutionCb,unboxingDepth+1,);if(passesUnification){return true}}return false}const unifyFunctionTypeIsMatchCandidate=(fnType,queryElem,mgensIn)=>{if(!typePassesFilter(queryElem.typeFilter,fnType.ty)){return false}if(fnType.id<0&&queryElem.id<0){if(mgensIn){if(mgensIn.has(fnType.id)&&mgensIn.get(fnType.id)!==queryElem.id){return false}for(const[fid,qid]of mgensIn.entries()){if(fnType.id!==fid&&queryElem.id===qid){return false}if(fnType.id===fid&&queryElem.id!==qid){return false}}}return true}else{if(queryElem.id===this.typeNameIdOfArrayOrSlice&&(fnType.id===this.typeNameIdOfSlice||fnType.id===this.typeNameIdOfArray)){}else if(queryElem.id===this.typeNameIdOfTupleOrUnit&&(fnType.id===this.typeNameIdOfTuple||fnType.id===this.typeNameIdOfUnit)){}else if(queryElem.id===this.typeNameIdOfHof&&(fnType.id===this.typeNameIdOfFn||fnType.id===this.typeNameIdOfFnMut||fnType.id===this.typeNameIdOfFnOnce)){}else if(fnType.id!==queryElem.id||queryElem.id===null){return false}if((fnType.generics.length+fnType.bindings.size)===0&&queryElem.generics.length!==0){return false}if(fnType.bindings.size0){const fnTypePath=fnType.path!==undefined&&fnType.path!==null?fnType.path.split("::"):[];if(queryElemPathLength>fnTypePath.length){return false}let i=0;for(const path of fnTypePath){if(path===queryElem.pathWithoutLast[i]){i+=1;if(i>=queryElemPathLength){break}}}if(i0){let mgensSolutionSet=[mgensIn];for(const[name,constraints]of queryElem.bindings.entries()){if(mgensSolutionSet.length===0){return false}if(!fnType.bindings.has(name)){return false}const fnTypeBindings=fnType.bindings.get(name);mgensSolutionSet=mgensSolutionSet.flatMap(mgens=>{const newSolutions=[];unifyFunctionTypes(fnTypeBindings,constraints,whereClause,mgens,newMgens=>{newSolutions.push(newMgens);return false},unboxingDepth,);return newSolutions})}if(mgensSolutionSet.length===0){return false}const binds=Array.from(fnType.bindings.entries()).flatMap(entry=>{const[name,constraints]=entry;if(queryElem.bindings.has(name)){return[]}else{return constraints}});if(simplifiedGenerics.length>0){simplifiedGenerics=[...simplifiedGenerics,...binds]}else{simplifiedGenerics=binds}return{simplifiedGenerics,mgens:mgensSolutionSet}}return{simplifiedGenerics,mgens:[mgensIn]}}function unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth,){if(unboxingDepth>=UNBOXING_LIMIT){return false}if(fnType.id<0&&queryElem.id>=0){if(!whereClause){return false}if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==0){return false}const mgensTmp=new Map(mgens);mgensTmp.set(fnType.id,null);return checkIfInList(whereClause[(-fnType.id)-1],queryElem,whereClause,mgensTmp,unboxingDepth,)}else if(fnType.generics.length>0||fnType.bindings.size>0){const simplifiedGenerics=[...fnType.generics,...Array.from(fnType.bindings.values()).flat(),];return checkIfInList(simplifiedGenerics,queryElem,whereClause,mgens,unboxingDepth,)}return false}function checkIfInList(list,elem,whereClause,mgens,unboxingDepth){for(const entry of list){if(checkType(entry,elem,whereClause,mgens,unboxingDepth)){return true}}return false}const checkType=(row,elem,whereClause,mgens,unboxingDepth)=>{if(unboxingDepth>=UNBOXING_LIMIT){return false}if(row.bindings.size===0&&elem.bindings.size===0){if(elem.id<0&&mgens===null){return row.id<0||checkIfInList(row.generics,elem,whereClause,mgens,unboxingDepth+1,)}if(row.id>0&&elem.id>0&&elem.pathWithoutLast.length===0&&typePassesFilter(elem.typeFilter,row.ty)&&elem.generics.length===0&&elem.id!==this.typeNameIdOfArrayOrSlice&&elem.id!==this.typeNameIdOfTupleOrUnit&&elem.id!==this.typeNameIdOfHof){return row.id===elem.id||checkIfInList(row.generics,elem,whereClause,mgens,unboxingDepth,)}}return unifyFunctionTypes([row],[elem],whereClause,mgens,null,unboxingDepth)};function checkPath(contains,ty){if(contains.length===0){return 0}const maxPathEditDistance=Math.floor(contains.reduce((acc,next)=>acc+next.length,0)/3,);let ret_dist=maxPathEditDistance+1;const path=ty.path.split("::");if(ty.parent&&ty.parent.name){path.push(ty.parent.name.toLowerCase())}const length=path.length;const clength=contains.length;pathiter:for(let i=length-clength;i>=0;i-=1){let dist_total=0;for(let x=0;xmaxPathEditDistance){continue pathiter}dist_total+=dist}}ret_dist=Math.min(ret_dist,Math.round(dist_total/clength))}return ret_dist>maxPathEditDistance?null:ret_dist}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER||filter===type)return true;const name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,descShard:item.descShard,descIndex:item.descIndex,exactPath:item.exactPath,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,bitIndex:item.bitIndex,implDisambiguator:item.implDisambiguator,}}const handleAliases=async(ret,query,filterCrates,currentCrate)=>{const lowerQuery=query.toLowerCase();const aliases=[];const crateAliases=[];if(filterCrates!==null){if(this.ALIASES.has(filterCrates)&&this.ALIASES.get(filterCrates).has(lowerQuery)){const query_aliases=this.ALIASES.get(filterCrates).get(lowerQuery);for(const alias of query_aliases){aliases.push(createAliasFromItem(this.searchIndex[alias]))}}}else{for(const[crate,crateAliasesIndex]of this.ALIASES){if(crateAliasesIndex.has(lowerQuery)){const pushTo=crate===currentCrate?crateAliases:aliases;const query_aliases=crateAliasesIndex.get(lowerQuery);for(const alias of query_aliases){pushTo.push(createAliasFromItem(this.searchIndex[alias]))}}}}const sortFunc=(aaa,bbb)=>{if(aaa.path{return this.searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex)?"":this.searchState.loadDesc(alias)};const[crateDescs,descs]=await Promise.all([Promise.all(crateAliases.map(fetchDesc)),Promise.all(aliases.map(fetchDesc)),]);const pushFunc=alias=>{alias.alias=query;const res=buildHrefAndPath(alias);alias.displayPath=pathSplitter(res[0]);alias.fullPath=alias.displayPath+alias.name;alias.href=res[1];ret.others.unshift(alias);if(ret.others.length>MAX_RESULTS){ret.others.pop()}};aliases.forEach((alias,i)=>{alias.desc=descs[i]});aliases.forEach(pushFunc);crateAliases.forEach((alias,i)=>{alias.desc=crateDescs[i]});crateAliases.forEach(pushFunc)};function addIntoResults(results,fullId,id,index,dist,path_dist,maxEditDistance){if(dist<=maxEditDistance||index!==-1){if(results.has(fullId)){const result=results.get(fullId);if(result.dontValidate||result.dist<=dist){return}}results.set(fullId,{id:id,index:index,dontValidate:parsedQuery.literalSearch,dist:dist,path_dist:path_dist,})}}function handleSingleArg(row,pos,elem,results_others,results_in_args,results_returned,maxEditDistance,){if(!row||(filterCrates!==null&&row.crate!==filterCrates)){return}let path_dist=0;const fullId=row.id;const tfpDist=compareTypeFingerprints(fullId,parsedQuery.typeFingerprint,);if(tfpDist!==null){const in_args=row.type&&row.type.inputs&&checkIfInList(row.type.inputs,elem,row.type.where_clause,null,0);const returned=row.type&&row.type.output&&checkIfInList(row.type.output,elem,row.type.where_clause,null,0);if(in_args){results_in_args.max_dist=Math.max(results_in_args.max_dist||0,tfpDist);const maxDist=results_in_args.sizenormalizedIndex&&normalizedIndex!==-1)){index=normalizedIndex}if(elem.fullPath.length>1){path_dist=checkPath(elem.pathWithoutLast,row);if(path_dist===null){return}}if(parsedQuery.literalSearch){if(row.word===elem.pathLast){addIntoResults(results_others,fullId,pos,index,0,path_dist)}return}const dist=editDistance(row.normalizedName,elem.normalizedPathLast,maxEditDistance);if(index===-1&&dist>maxEditDistance){return}addIntoResults(results_others,fullId,pos,index,dist,path_dist,maxEditDistance)}function handleArgs(row,pos,results){if(!row||(filterCrates!==null&&row.crate!==filterCrates)||!row.type){return}const tfpDist=compareTypeFingerprints(row.id,parsedQuery.typeFingerprint,);if(tfpDist===null){return}if(results.size>=MAX_RESULTS&&tfpDist>results.max_dist){return}if(!unifyFunctionTypes(row.type.inputs,parsedQuery.elems,row.type.where_clause,null,mgens=>{return unifyFunctionTypes(row.type.output,parsedQuery.returned,row.type.where_clause,mgens,null,0,)},0,)){return}results.max_dist=Math.max(results.max_dist||0,tfpDist);addIntoResults(results,row.id,pos,0,tfpDist,0,Number.MAX_VALUE)}const compareTypeFingerprints=(fullId,queryFingerprint)=>{const fh0=this.functionTypeFingerprint[fullId*4];const fh1=this.functionTypeFingerprint[(fullId*4)+1];const fh2=this.functionTypeFingerprint[(fullId*4)+2];const[qh0,qh1,qh2]=queryFingerprint;const[in0,in1,in2]=[fh0&qh0,fh1&qh1,fh2&qh2];if((in0 ^ qh0)||(in1 ^ qh1)||(in2 ^ qh2)){return null}return this.functionTypeFingerprint[(fullId*4)+3]};const innerRunQuery=()=>{const queryLen=parsedQuery.elems.reduce((acc,next)=>acc+next.pathLast.length,0)+parsedQuery.returned.reduce((acc,next)=>acc+next.pathLast.length,0);const maxEditDistance=Math.floor(queryLen/3);const genericSymbols=new Map();const convertNameToId=(elem,isAssocType)=>{const loweredName=elem.pathLast.toLowerCase();if(this.typeNameIdMap.has(loweredName)&&(isAssocType||!this.typeNameIdMap.get(loweredName).assocOnly)){elem.id=this.typeNameIdMap.get(loweredName).id}else if(!parsedQuery.literalSearch){let match=null;let matchDist=maxEditDistance+1;let matchName="";for(const[name,{id,assocOnly}]of this.typeNameIdMap){const dist=Math.min(editDistance(name,loweredName,maxEditDistance),editDistance(name,elem.normalizedPathLast,maxEditDistance),);if(dist<=matchDist&&dist<=maxEditDistance&&(isAssocType||!assocOnly)){if(dist===matchDist&&matchName>name){continue}match=id;matchDist=dist;matchName=name}}if(match!==null){parsedQuery.correction=matchName}elem.id=match}if((elem.id===null&&parsedQuery.totalElems>1&&elem.typeFilter===-1&&elem.generics.length===0&&elem.bindings.size===0)||elem.typeFilter===TY_GENERIC){if(genericSymbols.has(elem.name)){elem.id=genericSymbols.get(elem.name)}else{elem.id=-(genericSymbols.size+1);genericSymbols.set(elem.name,elem.id)}if(elem.typeFilter===-1&&elem.name.length>=3){const maxPartDistance=Math.floor(elem.name.length/3);let matchDist=maxPartDistance+1;let matchName="";for(const name of this.typeNameIdMap.keys()){const dist=editDistance(name,elem.name,maxPartDistance);if(dist<=matchDist&&dist<=maxPartDistance){if(dist===matchDist&&matchName>name){continue}matchDist=dist;matchName=name}}if(matchName!==""){parsedQuery.proposeCorrectionFrom=elem.name;parsedQuery.proposeCorrectionTo=matchName}}elem.typeFilter=TY_GENERIC}if(elem.generics.length>0&&elem.typeFilter===TY_GENERIC){parsedQuery.error=["Generic type parameter ",elem.name," does not accept generic parameters",]}for(const elem2 of elem.generics){convertNameToId(elem2)}elem.bindings=new Map(Array.from(elem.bindings.entries()).map(entry=>{const[name,constraints]=entry;if(!this.typeNameIdMap.has(name)){parsedQuery.error=["Type parameter ",name," does not exist",];return[null,[]]}for(const elem2 of constraints){convertNameToId(elem2)}return[this.typeNameIdMap.get(name).id,constraints]}),)};const fps=new Set();for(const elem of parsedQuery.elems){convertNameToId(elem);this.buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint,fps)}for(const elem of parsedQuery.returned){convertNameToId(elem);this.buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint,fps)}if(parsedQuery.foundElems===1&&!parsedQuery.hasReturnArrow){if(parsedQuery.elems.length===1){const elem=parsedQuery.elems[0];const length=this.searchIndex.length;for(let i=0,nSearchIndex=length;i0){const sortQ=(a,b)=>{const ag=a.generics.length===0&&a.bindings.size===0;const bg=b.generics.length===0&&b.bindings.size===0;if(ag!==bg){return ag-bg}const ai=a.id>0;const bi=b.id>0;return ai-bi};parsedQuery.elems.sort(sortQ);parsedQuery.returned.sort(sortQ);for(let i=0,nSearchIndex=this.searchIndex.length;i{const descs=await Promise.all(list.map(result=>{return this.searchIndexEmptyDesc.get(result.crate).contains(result.bitIndex)?"":this.searchState.loadDesc(result)}));for(const[i,result]of list.entries()){result.desc=descs[i]}}));if(parsedQuery.error!==null&&ret.others.length!==0){ret.query.error=null}return ret}}let rawSearchIndex;let docSearch;const longItemTypes=["keyword","primitive type","module","extern crate","re-export","struct","enum","function","type alias","static","trait","","trait method","method","struct field","enum variant","macro","assoc type","constant","assoc const","union","foreign type","existential type","attribute macro","derive macro","trait alias",];let currentResults;function printTab(nb){let iter=0;let foundCurrentTab=false;let foundCurrentResultSet=false;onEachLazy(document.getElementById("search-tabs").childNodes,elem=>{if(nb===iter){addClass(elem,"selected");foundCurrentTab=true}else{removeClass(elem,"selected")}iter+=1});const isTypeSearch=(nb>0||iter===1);iter=0;onEachLazy(document.getElementById("results").childNodes,elem=>{if(nb===iter){addClass(elem,"active");foundCurrentResultSet=true}else{removeClass(elem,"active")}iter+=1});if(foundCurrentTab&&foundCurrentResultSet){searchState.currentTab=nb;const correctionsElem=document.getElementsByClassName("search-corrections");if(isTypeSearch){removeClass(correctionsElem[0],"hidden")}else{addClass(correctionsElem[0],"hidden")}}else if(nb!==0){printTab(0)}}function buildUrl(search,filterCrates){let extra="?search="+encodeURIComponent(search);if(filterCrates!==null){extra+="&filter-crate="+encodeURIComponent(filterCrates)}return getNakedUrl()+extra+window.location.hash}function getFilterCrates(){const elem=document.getElementById("crate-search");if(elem&&elem.value!=="all crates"&&window.searchIndex.has(elem.value)){return elem.value}return null}function nextTab(direction){const next=(searchState.currentTab+direction+3)%searchState.focusedByTab.length;searchState.focusedByTab[searchState.currentTab]=document.activeElement;printTab(next);focusSearchResult()}function focusSearchResult(){const target=searchState.focusedByTab[searchState.currentTab]||document.querySelectorAll(".search-results.active a").item(0)||document.querySelectorAll("#search-tabs button").item(searchState.currentTab);searchState.focusedByTab[searchState.currentTab]=null;if(target){target.focus()}}async function addTab(array,query,display){const extraClass=display?" active":"";const output=document.createElement("div");if(array.length>0){output.className="search-results "+extraClass;for(const item of array){const name=item.name;const type=itemTypes[item.ty];const longType=longItemTypes[item.ty];const typeName=longType.length!==0?`${longType}`:"?";const link=document.createElement("a");link.className="result-"+type;link.href=item.href;const resultName=document.createElement("div");resultName.className="result-name";resultName.insertAdjacentHTML("beforeend",`${typeName}`);link.appendChild(resultName);let alias=" ";if(item.is_alias){alias=`
\ +${item.alias} - see \ +
`}resultName.insertAdjacentHTML("beforeend",`
${alias}\ +${item.displayPath}${name}\ +
`);const description=document.createElement("div");description.className="desc";description.insertAdjacentHTML("beforeend",item.desc);link.appendChild(description);output.appendChild(link)}}else if(query.error===null){output.className="search-failed"+extraClass;output.innerHTML="No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:"}return[output,array.length]}function makeTabHeader(tabNb,text,nbElems){const fmtNbElems=nbElems<10?`\u{2007}(${nbElems})\u{2007}\u{2007}`:nbElems<100?`\u{2007}(${nbElems})\u{2007}`:`\u{2007}(${nbElems})`;if(searchState.currentTab===tabNb){return""}return""}async function showResults(results,go_to_first,filterCrates){const search=searchState.outputElement();if(go_to_first||(results.others.length===1&&getSettingValue("go-to-only-result")==="true")){window.onunload=()=>{};searchState.removeQueryParameters();const elem=document.createElement("a");elem.href=results.others[0].href;removeClass(elem,"active");document.body.appendChild(elem);elem.click();return}if(results.query===undefined){results.query=DocSearch.parseQuery(searchState.input.value)}currentResults=results.query.userQuery;const[ret_others,ret_in_args,ret_returned]=await Promise.all([addTab(results.others,results.query,true),addTab(results.in_args,results.query,false),addTab(results.returned,results.query,false),]);let currentTab=searchState.currentTab;if((currentTab===0&&ret_others[1]===0)||(currentTab===1&&ret_in_args[1]===0)||(currentTab===2&&ret_returned[1]===0)){if(ret_others[1]!==0){currentTab=0}else if(ret_in_args[1]!==0){currentTab=1}else if(ret_returned[1]!==0){currentTab=2}}let crates="";if(rawSearchIndex.size>1){crates="
in 
"+"
"}let output=`
\ +

Results

${crates}
`;if(results.query.error!==null){const error=results.query.error;error.forEach((value,index)=>{value=value.split("<").join("<").split(">").join(">");if(index%2!==0){error[index]=`${value.replaceAll(" ", " ")}`}else{error[index]=value}});output+=`

Query parser error: "${error.join("")}".

`;output+="
"+makeTabHeader(0,"In Names",ret_others[1])+"
";currentTab=0}else if(results.query.foundElems<=1&&results.query.returned.length===0){output+="
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"}else{const signatureTabTitle=results.query.elems.length===0?"In Function Return Types":results.query.returned.length===0?"In Function Parameters":"In Function Signatures";output+="
"+makeTabHeader(0,signatureTabTitle,ret_others[1])+"
";currentTab=0}if(results.query.correction!==null){const orig=results.query.returned.length>0?results.query.returned[0].name:results.query.elems[0].name;output+="

"+`Type "${orig}" not found. `+"Showing results for closest type name "+`"${results.query.correction}" instead.

`}if(results.query.proposeCorrectionFrom!==null){const orig=results.query.proposeCorrectionFrom;const targ=results.query.proposeCorrectionTo;output+="

"+`Type "${orig}" not found and used as generic parameter. `+`Consider searching for "${targ}" instead.

`}const resultsElem=document.createElement("div");resultsElem.id="results";resultsElem.appendChild(ret_others[0]);resultsElem.appendChild(ret_in_args[0]);resultsElem.appendChild(ret_returned[0]);search.innerHTML=output;if(searchState.rustdocToolbar){search.querySelector(".main-heading").appendChild(searchState.rustdocToolbar)}const crateSearch=document.getElementById("crate-search");if(crateSearch){crateSearch.addEventListener("input",updateCrate)}search.appendChild(resultsElem);searchState.showResults(search);const elems=document.getElementById("search-tabs").childNodes;searchState.focusedByTab=[];let i=0;for(const elem of elems){const j=i;elem.onclick=()=>printTab(j);searchState.focusedByTab.push(null);i+=1}printTab(currentTab)}function updateSearchHistory(url){if(!browserSupportsHistoryApi()){return}const params=searchState.getQueryStringParams();if(!history.state&&!params.search){history.pushState(null,"",url)}else{history.replaceState(null,"",url)}}async function search(forced){const query=DocSearch.parseQuery(searchState.input.value.trim());let filterCrates=getFilterCrates();if(!forced&&query.userQuery===currentResults){if(query.userQuery.length>0){putBackSearch()}return}searchState.setLoadingSearch();const params=searchState.getQueryStringParams();if(filterCrates===null&¶ms["filter-crate"]!==undefined){filterCrates=params["filter-crate"]}searchState.title="\""+query.original+"\" Search - Rust";updateSearchHistory(buildUrl(query.original,filterCrates));await showResults(await docSearch.execQuery(query,filterCrates,window.currentCrate),params.go_to_first,filterCrates)}function onSearchSubmit(e){e.preventDefault();searchState.clearInputTimeout();search()}function putBackSearch(){const search_input=searchState.input;if(!searchState.input){return}if(search_input.value!==""&&!searchState.isDisplayed()){searchState.showResults();if(browserSupportsHistoryApi()){history.replaceState(null,"",buildUrl(search_input.value,getFilterCrates()))}document.title=searchState.title}}function registerSearchEvents(){const params=searchState.getQueryStringParams();if(searchState.input.value===""){searchState.input.value=params.search||""}const searchAfter500ms=()=>{searchState.clearInputTimeout();if(searchState.input.value.length===0){searchState.hideResults()}else{searchState.timeout=setTimeout(search,500)}};searchState.input.onkeyup=searchAfter500ms;searchState.input.oninput=searchAfter500ms;document.getElementsByClassName("search-form")[0].onsubmit=onSearchSubmit;searchState.input.onchange=e=>{if(e.target!==document.activeElement){return}searchState.clearInputTimeout();setTimeout(search,0)};searchState.input.onpaste=searchState.input.onchange;searchState.outputElement().addEventListener("keydown",e=>{if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey){return}if(e.which===38){const previous=document.activeElement.previousElementSibling;if(previous){previous.focus()}else{searchState.focus()}e.preventDefault()}else if(e.which===40){const next=document.activeElement.nextElementSibling;if(next){next.focus()}const rect=document.activeElement.getBoundingClientRect();if(window.innerHeight-rect.bottom{if(e.which===40){focusSearchResult();e.preventDefault()}});searchState.input.addEventListener("focus",()=>{putBackSearch()});searchState.input.addEventListener("blur",()=>{searchState.input.placeholder=searchState.input.origPlaceholder});if(browserSupportsHistoryApi()){const previousTitle=document.title;window.addEventListener("popstate",e=>{const params=searchState.getQueryStringParams();document.title=previousTitle;currentResults=null;if(params.search&¶ms.search.length>0){searchState.input.value=params.search;e.preventDefault();search()}else{searchState.input.value="";searchState.hideResults()}})}window.onpageshow=()=>{const qSearch=searchState.getQueryStringParams().search;if(searchState.input.value===""&&qSearch){searchState.input.value=qSearch}search()}}function updateCrate(ev){if(ev.target.value==="all crates"){const query=searchState.input.value.trim();updateSearchHistory(buildUrl(query,null))}currentResults=null;search(true)}function initSearch(searchIndx){rawSearchIndex=searchIndx;if(typeof window!=="undefined"){docSearch=new DocSearch(rawSearchIndex,ROOT_PATH,searchState);registerSearchEvents();if(window.searchState.getQueryStringParams().search){search()}}else if(typeof exports!=="undefined"){docSearch=new DocSearch(rawSearchIndex,ROOT_PATH,searchState);exports.docSearch=docSearch;exports.parseQuery=DocSearch.parseQuery}}if(typeof exports!=="undefined"){exports.initSearch=initSearch}if(typeof window!=="undefined"){window.initSearch=initSearch;if(window.searchIndex!==undefined){initSearch(window.searchIndex)}}else{initSearch(new Map())}})() \ No newline at end of file diff --git a/static.files/settings-805db61a62df4bd2.js b/static.files/settings-805db61a62df4bd2.js new file mode 100644 index 0000000..4a30479 --- /dev/null +++ b/static.files/settings-805db61a62df4bd2.js @@ -0,0 +1,17 @@ +"use strict";(function(){const isSettingsPage=window.location.pathname.endsWith("/settings.html");function changeSetting(settingName,value){if(settingName==="theme"){const useSystem=value==="system preference"?"true":"false";updateLocalStorage("use-system-theme",useSystem)}updateLocalStorage(settingName,value);switch(settingName){case"theme":case"preferred-dark-theme":case"preferred-light-theme":updateTheme();updateLightAndDark();break;case"line-numbers":if(value===true){window.rustdoc_add_line_numbers_to_examples()}else{window.rustdoc_remove_line_numbers_from_examples()}break;case"hide-sidebar":if(value===true){addClass(document.documentElement,"hide-sidebar")}else{removeClass(document.documentElement,"hide-sidebar")}break;case"hide-toc":if(value===true){addClass(document.documentElement,"hide-toc")}else{removeClass(document.documentElement,"hide-toc")}break;case"hide-modnav":if(value===true){addClass(document.documentElement,"hide-modnav")}else{removeClass(document.documentElement,"hide-modnav")}break}}function showLightAndDark(){removeClass(document.getElementById("preferred-light-theme"),"hidden");removeClass(document.getElementById("preferred-dark-theme"),"hidden")}function hideLightAndDark(){addClass(document.getElementById("preferred-light-theme"),"hidden");addClass(document.getElementById("preferred-dark-theme"),"hidden")}function updateLightAndDark(){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||(useSystem===null&&getSettingValue("theme")===null)){showLightAndDark()}else{hideLightAndDark()}}function setEvents(settingsElement){updateLightAndDark();onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"),toggle=>{const settingId=toggle.id;const settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=()=>{changeSetting(toggle.id,toggle.checked)}});onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"),elem=>{const settingId=elem.name;let settingValue=getSettingValue(settingId);if(settingId==="theme"){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||settingValue===null){settingValue=useSystem==="false"?"light":"system preference"}}if(settingValue!==null&&settingValue!=="null"){elem.checked=settingValue===elem.value}elem.addEventListener("change",ev=>{changeSetting(ev.target.name,ev.target.value)})})}function buildSettingsPageSections(settings){let output="";for(const setting of settings){if(setting==="hr"){output+="
";continue}const js_data_name=setting["js_name"];const setting_name=setting["name"];if(setting["options"]!==undefined){output+=`\ +
+
${setting_name}
+
`;onEach(setting["options"],option=>{const checked=option===setting["default"]?" checked":"";const full=`${js_data_name}-${option.replace(/ /g,"-")}`;output+=`\ + `});output+=`\ +
+
`}else{const checked=setting["default"]===true?" checked":"";output+=`\ +
\ + \ +
`}}return output}function buildSettingsPage(){const theme_names=getVar("themes").split(",").filter(t=>t);theme_names.push("light","dark","ayu");const settings=[{"name":"Theme","js_name":"theme","default":"system preference","options":theme_names.concat("system preference"),},{"name":"Preferred light theme","js_name":"preferred-light-theme","default":"light","options":theme_names,},{"name":"Preferred dark theme","js_name":"preferred-dark-theme","default":"dark","options":theme_names,},{"name":"Auto-hide item contents for large items","js_name":"auto-hide-large-items","default":true,},{"name":"Auto-hide item methods' documentation","js_name":"auto-hide-method-docs","default":false,},{"name":"Auto-hide trait implementation documentation","js_name":"auto-hide-trait-implementations","default":false,},{"name":"Directly go to item in search if there is only one result","js_name":"go-to-only-result","default":false,},{"name":"Show line numbers on code examples","js_name":"line-numbers","default":false,},{"name":"Hide persistent navigation bar","js_name":"hide-sidebar","default":false,},{"name":"Hide table of contents","js_name":"hide-toc","default":false,},{"name":"Hide module navigation","js_name":"hide-modnav","default":false,},{"name":"Disable keyboard shortcuts","js_name":"disable-shortcuts","default":false,},];const elementKind=isSettingsPage?"section":"div";const innerHTML=`
${buildSettingsPageSections(settings)}
`;const el=document.createElement(elementKind);el.id="settings";if(!isSettingsPage){el.className="popover"}el.innerHTML=innerHTML;if(isSettingsPage){document.getElementById(MAIN_ID).appendChild(el)}else{el.setAttribute("tabindex","-1");getSettingsButton().appendChild(el)}return el}const settingsMenu=buildSettingsPage();function displaySettings(){settingsMenu.style.display="";onEachLazy(settingsMenu.querySelectorAll("input[type='checkbox']"),el=>{const val=getSettingValue(el.id);const checked=val==="true";if(checked!==el.checked&&val!==null){el.checked=checked}})}function settingsBlurHandler(event){if(!getHelpButton().contains(document.activeElement)&&!getHelpButton().contains(event.relatedTarget)&&!getSettingsButton().contains(document.activeElement)&&!getSettingsButton().contains(event.relatedTarget)){window.hidePopoverMenus()}}if(!isSettingsPage){const settingsButton=getSettingsButton();const settingsMenu=document.getElementById("settings");settingsButton.onclick=event=>{if(settingsMenu.contains(event.target)){return}event.preventDefault();const shouldDisplaySettings=settingsMenu.style.display==="none";window.hideAllModals();if(shouldDisplaySettings){displaySettings()}};settingsButton.onblur=settingsBlurHandler;settingsButton.querySelector("a").onblur=settingsBlurHandler;onEachLazy(settingsMenu.querySelectorAll("input"),el=>{el.onblur=settingsBlurHandler});settingsMenu.onblur=settingsBlurHandler}setTimeout(()=>{setEvents(settingsMenu);if(!isSettingsPage){displaySettings()}removeClass(getSettingsButton(),"rotate")},0)})() \ No newline at end of file diff --git a/static.files/src-script-e66d777a5a92e9b2.js b/static.files/src-script-e66d777a5a92e9b2.js new file mode 100644 index 0000000..d0aebb8 --- /dev/null +++ b/static.files/src-script-e66d777a5a92e9b2.js @@ -0,0 +1 @@ +"use strict";(function(){const rootPath=getVar("root-path");const NAME_OFFSET=0;const DIRS_OFFSET=1;const FILES_OFFSET=2;const RUSTDOC_MOBILE_BREAKPOINT=700;function closeSidebarIfMobile(){if(window.innerWidth{removeClass(document.documentElement,"src-sidebar-expanded");updateLocalStorage("source-sidebar-show","false")};window.rustdocShowSourceSidebar=()=>{addClass(document.documentElement,"src-sidebar-expanded");updateLocalStorage("source-sidebar-show","true")};window.rustdocToggleSrcSidebar=()=>{if(document.documentElement.classList.contains("src-sidebar-expanded")){window.rustdocCloseSourceSidebar()}else{window.rustdocShowSourceSidebar()}};function createSrcSidebar(){const container=document.querySelector("nav.sidebar");const sidebar=document.createElement("div");sidebar.id="src-sidebar";let hasFoundFile=false;for(const[key,source]of srcIndex){source[NAME_OFFSET]=key;hasFoundFile=createDirEntry(source,sidebar,"",hasFoundFile)}container.appendChild(sidebar);const selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}}function highlightSrcLines(){const match=window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);if(!match){return}let from=parseInt(match[1],10);let to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to{onEachLazy(e.getElementsByTagName("a"),i_e=>{removeClass(i_e,"line-highlighted")})});for(let i=from;i<=to;++i){elem=document.getElementById(i);if(!elem){break}addClass(elem,"line-highlighted")}}const handleSrcHighlight=(function(){let prev_line_id=0;const set_fragment=name=>{const x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSrcLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return ev=>{let cur_line_id=parseInt(ev.target.id,10);if(isNaN(cur_line_id)||ev.ctrlKey||ev.altKey||ev.metaKey){return}ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){const tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());window.addEventListener("hashchange",highlightSrcLines);onEachLazy(document.getElementsByClassName("src-line-numbers"),el=>{el.addEventListener("click",handleSrcHighlight)});highlightSrcLines();window.createSrcSidebar=createSrcSidebar})() \ No newline at end of file diff --git a/static.files/storage-1d39b6787ed640ff.js b/static.files/storage-1d39b6787ed640ff.js new file mode 100644 index 0000000..5aac776 --- /dev/null +++ b/static.files/storage-1d39b6787ed640ff.js @@ -0,0 +1,23 @@ +"use strict";const builtinThemes=["light","dark","ayu"];const darkThemes=["dark","ayu"];window.currentTheme=document.getElementById("themeStyle");const settingsDataset=(function(){const settingsElement=document.getElementById("default-settings");return settingsElement&&settingsElement.dataset?settingsElement.dataset:null})();function getSettingValue(settingName){const current=getCurrentValue(settingName);if(current===null&&settingsDataset!==null){const def=settingsDataset[settingName.replace(/-/g,"_")];if(def!==undefined){return def}}return current}const localStoredTheme=getSettingValue("theme");function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(elem&&elem.classList){elem.classList.add(className)}}function removeClass(elem,className){if(elem&&elem.classList){elem.classList.remove(className)}}function onEach(arr,func){for(const elem of arr){if(func(elem)){return true}}return false}function onEachLazy(lazyArray,func){return onEach(Array.prototype.slice.call(lazyArray),func)}function updateLocalStorage(name,value){try{window.localStorage.setItem("rustdoc-"+name,value)}catch(e){}}function getCurrentValue(name){try{return window.localStorage.getItem("rustdoc-"+name)}catch(e){return null}}const getVar=(function getVar(name){const el=document.querySelector("head > meta[name='rustdoc-vars']");return el?el.attributes["data-"+name].value:null});function switchTheme(newThemeName,saveTheme){const themeNames=getVar("themes").split(",").filter(t=>t);themeNames.push(...builtinThemes);if(themeNames.indexOf(newThemeName)===-1){return}if(saveTheme){updateLocalStorage("theme",newThemeName)}document.documentElement.setAttribute("data-theme",newThemeName);if(builtinThemes.indexOf(newThemeName)!==-1){if(window.currentTheme){window.currentTheme.parentNode.removeChild(window.currentTheme);window.currentTheme=null}}else{const newHref=getVar("root-path")+encodeURIComponent(newThemeName)+getVar("resource-suffix")+".css";if(!window.currentTheme){if(document.readyState==="loading"){document.write(``);window.currentTheme=document.getElementById("themeStyle")}else{window.currentTheme=document.createElement("link");window.currentTheme.rel="stylesheet";window.currentTheme.id="themeStyle";window.currentTheme.href=newHref;document.documentElement.appendChild(window.currentTheme)}}else if(newHref!==window.currentTheme.href){window.currentTheme.href=newHref}}}const updateTheme=(function(){const mql=window.matchMedia("(prefers-color-scheme: dark)");function updateTheme(){if(getSettingValue("use-system-theme")!=="false"){const lightTheme=getSettingValue("preferred-light-theme")||"light";const darkTheme=getSettingValue("preferred-dark-theme")||"dark";updateLocalStorage("use-system-theme","true");switchTheme(mql.matches?darkTheme:lightTheme,true)}else{switchTheme(getSettingValue("theme"),false)}}mql.addEventListener("change",updateTheme);return updateTheme})();if(getSettingValue("use-system-theme")!=="false"&&window.matchMedia){if(getSettingValue("use-system-theme")===null&&getSettingValue("preferred-dark-theme")===null&&darkThemes.indexOf(localStoredTheme)>=0){updateLocalStorage("preferred-dark-theme",localStoredTheme)}}updateTheme();if(getSettingValue("source-sidebar-show")==="true"){addClass(document.documentElement,"src-sidebar-expanded")}if(getSettingValue("hide-sidebar")==="true"){addClass(document.documentElement,"hide-sidebar")}if(getSettingValue("hide-toc")==="true"){addClass(document.documentElement,"hide-toc")}if(getSettingValue("hide-modnav")==="true"){addClass(document.documentElement,"hide-modnav")}function updateSidebarWidth(){const desktopSidebarWidth=getSettingValue("desktop-sidebar-width");if(desktopSidebarWidth&&desktopSidebarWidth!=="null"){document.documentElement.style.setProperty("--desktop-sidebar-width",desktopSidebarWidth+"px",)}const srcSidebarWidth=getSettingValue("src-sidebar-width");if(srcSidebarWidth&&srcSidebarWidth!=="null"){document.documentElement.style.setProperty("--src-sidebar-width",srcSidebarWidth+"px",)}}updateSidebarWidth();window.addEventListener("pageshow",ev=>{if(ev.persisted){setTimeout(updateTheme,0);setTimeout(updateSidebarWidth,0)}});class RustdocSearchElement extends HTMLElement{constructor(){super()}connectedCallback(){const rootPath=getVar("root-path");const currentCrate=getVar("current-crate");this.innerHTML=``}}window.customElements.define("rustdoc-search",RustdocSearchElement);class RustdocToolbarElement extends HTMLElement{constructor(){super()}connectedCallback(){if(this.firstElementChild){return}const rootPath=getVar("root-path");this.innerHTML=` +
+ Settings +
+
+ Help +
+ `}}window.customElements.define("rustdoc-toolbar",RustdocToolbarElement) \ No newline at end of file diff --git a/toc.html b/toc.html new file mode 100644 index 0000000..7a8c092 --- /dev/null +++ b/toc.html @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + +
  1. Introduction
  2. Getting Started
    1. Install
    2. Getting Started - cv2
    3. Getting Started - DSL
  3. Concepts & Data Model
  4. Tools
    1. vidformer-py
    2. libvidformer
  5. Filters
    1. Built-in Filters
    2. OpenCV/cv2
    3. User-Defined Filters
  6. Roadmap
  7. FAQ
+ + diff --git a/toc.js b/toc.js new file mode 100644 index 0000000..5e53022 --- /dev/null +++ b/toc.js @@ -0,0 +1,70 @@ +// Populate the sidebar +// +// This is a script, and not included directly in the page, to control the total size of the book. +// The TOC contains an entry for each page, so if each page includes a copy of the TOC, +// the total size of the page becomes O(n**2). +class MDBookSidebarScrollbox extends HTMLElement { + constructor() { + super(); + } + connectedCallback() { + this.innerHTML = '
  1. Introduction
  2. Getting Started
    1. Install
    2. Getting Started - cv2
    3. Getting Started - DSL
  3. Concepts & Data Model
  4. Tools
    1. vidformer-py
    2. libvidformer
  5. Filters
    1. Built-in Filters
    2. OpenCV/cv2
    3. User-Defined Filters
  6. Roadmap
  7. FAQ
'; + // Set the current, active page, and reveal it if it's hidden + let current_page = document.location.href.toString(); + if (current_page.endsWith("/")) { + current_page += "index.html"; + } + var links = Array.prototype.slice.call(this.querySelectorAll("a")); + var l = links.length; + for (var i = 0; i < l; ++i) { + var link = links[i]; + var href = link.getAttribute("href"); + if (href && !href.startsWith("#") && !/^(?:[a-z+]+:)?\/\//.test(href)) { + link.href = path_to_root + href; + } + // The "index" page is supposed to alias the first chapter in the book. + if (link.href === current_page || (i === 0 && path_to_root === "" && current_page.endsWith("/index.html"))) { + link.classList.add("active"); + var parent = link.parentElement; + if (parent && parent.classList.contains("chapter-item")) { + parent.classList.add("expanded"); + } + while (parent) { + if (parent.tagName === "LI" && parent.previousElementSibling) { + if (parent.previousElementSibling.classList.contains("chapter-item")) { + parent.previousElementSibling.classList.add("expanded"); + } + } + parent = parent.parentElement; + } + } + } + // Track and set sidebar scroll position + this.addEventListener('click', function(e) { + if (e.target.tagName === 'A') { + sessionStorage.setItem('sidebar-scroll', this.scrollTop); + } + }, { passive: true }); + var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll'); + sessionStorage.removeItem('sidebar-scroll'); + if (sidebarScrollTop) { + // preserve sidebar scroll position when navigating via links within sidebar + this.scrollTop = sidebarScrollTop; + } else { + // scroll sidebar to current active section when navigating via "next/previous chapter" buttons + var activeSection = document.querySelector('#sidebar .active'); + if (activeSection) { + activeSection.scrollIntoView({ block: 'center' }); + } + } + // Toggle buttons + var sidebarAnchorToggles = document.querySelectorAll('#sidebar a.toggle'); + function toggleSection(ev) { + ev.currentTarget.parentElement.classList.toggle('expanded'); + } + Array.from(sidebarAnchorToggles).forEach(function (el) { + el.addEventListener('click', toggleSection); + }); + } +} +window.customElements.define("mdbook-sidebar-scrollbox", MDBookSidebarScrollbox); diff --git a/tomorrow-night.css b/tomorrow-night.css new file mode 100644 index 0000000..11752b8 --- /dev/null +++ b/tomorrow-night.css @@ -0,0 +1,104 @@ +/* Tomorrow Night Theme */ +/* https://github.com/jmblog/color-themes-for-highlightjs */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* https://github.com/jmblog/color-themes-for-highlightjs */ + +/* Tomorrow Comment */ +.hljs-comment { + color: #969896; +} + +/* Tomorrow Red */ +.hljs-variable, +.hljs-attribute, +.hljs-attr, +.hljs-tag, +.hljs-regexp, +.ruby .hljs-constant, +.xml .hljs-tag .hljs-title, +.xml .hljs-pi, +.xml .hljs-doctype, +.html .hljs-doctype, +.css .hljs-id, +.css .hljs-class, +.css .hljs-pseudo { + color: #cc6666; +} + +/* Tomorrow Orange */ +.hljs-number, +.hljs-preprocessor, +.hljs-pragma, +.hljs-built_in, +.hljs-literal, +.hljs-params, +.hljs-constant { + color: #de935f; +} + +/* Tomorrow Yellow */ +.ruby .hljs-class .hljs-title, +.css .hljs-rule .hljs-attribute { + color: #f0c674; +} + +/* Tomorrow Green */ +.hljs-string, +.hljs-value, +.hljs-inheritance, +.hljs-header, +.hljs-name, +.ruby .hljs-symbol, +.xml .hljs-cdata { + color: #b5bd68; +} + +/* Tomorrow Aqua */ +.hljs-title, +.hljs-section, +.css .hljs-hexcolor { + color: #8abeb7; +} + +/* Tomorrow Blue */ +.hljs-function, +.python .hljs-decorator, +.python .hljs-title, +.ruby .hljs-function .hljs-title, +.ruby .hljs-title .hljs-keyword, +.perl .hljs-sub, +.javascript .hljs-title, +.coffeescript .hljs-title { + color: #81a2be; +} + +/* Tomorrow Purple */ +.hljs-keyword, +.javascript .hljs-function { + color: #b294bb; +} + +.hljs { + display: block; + overflow-x: auto; + background: #1d1f21; + color: #c5c8c6; +} + +.coffeescript .javascript, +.javascript .xml, +.tex .hljs-formula, +.xml .javascript, +.xml .vbscript, +.xml .css, +.xml .hljs-cdata { + opacity: 0.5; +} + +.hljs-addition { + color: #718c00; +} + +.hljs-deletion { + color: #c82829; +} diff --git a/tools.html b/tools.html new file mode 100644 index 0000000..a8c46d1 --- /dev/null +++ b/tools.html @@ -0,0 +1,254 @@ + + + + + + Tools - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

The vidformer Tools

+

vidformer is a highly modular suite of tools that work together:

+
    +
  • +

    vidformer-py: A Python 🐍 client for declarative video synthesis

    +
      +
    • Provides an easy-to-use library for symbolically representing transformed videos
    • +
    • Acts as a client for a VoD server (i.e., for yrden)
    • +
    • Using vidformer-py is the best place to get started
    • +
    +
  • +
  • +

    libvidformer: The core data-oriented declarative video editing library

    +
      +
    • An embedded video processing execution engine with low-level interfaces
    • +
    • Systems code, written in Rust 🦀
    • +
    • You should use if: You are building a VDBMS or other multimodal data-system infrastructure.
    • +
    • You should not use if: You just want to use vidformer in your workflows or projects.
    • +
    +
  • +
  • +

    yrden: A vidformer Video-on-Demand server

    +
      +
    • Provides vidformer services over a REST-style API
    • +
    • Allows for client libraries to be written in any language
    • +
    • Serves video results via HLS streams
    • +
    • Designed for local single-tenant use
    • +
    • You should use if: You want to create faster video results in your workflows or projects.
    • +
    • Note that yrden servers may be spun up transparently by client libraries, so you might use yrden without realizing it.
    • +
    +
  • +
  • +

    igni: A planned scale-out Video-on-Demand server

    +
      +
    • Will allow for scalable and secure public-facing VOD endpoints
    • +
    +
  • +
+

Client libraries in other languages: +Writing a vidformer client library for other languages is simple. +It's a few hundred lines of code, and you just have to construct some JSON. +Contributions or suggestions for other languages are welcome.

+

Other VoD servers: +We provide yrden as a simple reference VoD server implementation. +If you want to scale-out deployments, multi-tenant deployments, or deep integration with a specific system, writing another VoD server is needed. (In progress work)

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/trait.impl/core/clone/trait.Clone.js b/trait.impl/core/clone/trait.Clone.js new file mode 100644 index 0000000..3147c7d --- /dev/null +++ b/trait.impl/core/clone/trait.Clone.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl Clone for RangeTsFormat"],["impl Clone for Val"],["impl Clone for DataExpr"],["impl Clone for Expr"],["impl Clone for FrameExpr"],["impl Clone for IndexConst"],["impl Clone for Frame"],["impl Clone for FrameType"],["impl Clone for Service"],["impl Clone for FilterExpr"],["impl Clone for FrameSource"],["impl Clone for SourceVideoStreamMeta"],["impl Clone for Config"],["impl Clone for EncoderConfig"],["impl Clone for Range"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[4007]} \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.Eq.js b/trait.impl/core/cmp/trait.Eq.js new file mode 100644 index 0000000..415d11b --- /dev/null +++ b/trait.impl/core/cmp/trait.Eq.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl Eq for IndexConst"],["impl Eq for FrameType"],["impl Eq for FrameSource"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[792]} \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.Ord.js b/trait.impl/core/cmp/trait.Ord.js new file mode 100644 index 0000000..72a9178 --- /dev/null +++ b/trait.impl/core/cmp/trait.Ord.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl Ord for IndexConst"],["impl Ord for FrameSource"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[536]} \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.PartialEq.js b/trait.impl/core/cmp/trait.PartialEq.js new file mode 100644 index 0000000..10757f1 --- /dev/null +++ b/trait.impl/core/cmp/trait.PartialEq.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl PartialEq for IndexConst"],["impl PartialEq for FrameType"],["impl PartialEq for FrameSource"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[855]} \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.PartialOrd.js b/trait.impl/core/cmp/trait.PartialOrd.js new file mode 100644 index 0000000..3723800 --- /dev/null +++ b/trait.impl/core/cmp/trait.PartialOrd.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl PartialOrd for IndexConst"],["impl PartialOrd for FrameSource"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[578]} \ No newline at end of file diff --git a/trait.impl/core/default/trait.Default.js b/trait.impl/core/default/trait.Default.js new file mode 100644 index 0000000..a6a4975 --- /dev/null +++ b/trait.impl/core/default/trait.Default.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl Default for Service"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[296]} \ No newline at end of file diff --git a/trait.impl/core/error/trait.Error.js b/trait.impl/core/error/trait.Error.js new file mode 100644 index 0000000..d7e653c --- /dev/null +++ b/trait.impl/core/error/trait.Error.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl Error for Error"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[257]} \ No newline at end of file diff --git a/trait.impl/core/fmt/trait.Debug.js b/trait.impl/core/fmt/trait.Debug.js new file mode 100644 index 0000000..282eb93 --- /dev/null +++ b/trait.impl/core/fmt/trait.Debug.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl Debug for Error"],["impl Debug for Val"],["impl Debug for DataExpr"],["impl Debug for Expr"],["impl Debug for FrameExpr"],["impl Debug for IndexConst"],["impl Debug for JsonArary"],["impl Debug for BoundingBoxBound"],["impl Debug for Frame"],["impl Debug for FrameType"],["impl Debug for Service"],["impl Debug for FilterExpr"],["impl Debug for FrameSource"],["impl Debug for SourceFileMeta"],["impl Debug for SourceVideoStreamMeta"],["impl Debug for JsonSpec"],["impl Debug for CodecDescriptor"],["impl Debug for Config"],["impl Debug for EncoderConfig"],["impl Debug for Stats"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[5325]} \ No newline at end of file diff --git a/trait.impl/core/fmt/trait.Display.js b/trait.impl/core/fmt/trait.Display.js new file mode 100644 index 0000000..00c7d53 --- /dev/null +++ b/trait.impl/core/fmt/trait.Display.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl Display for Error"],["impl Display for DataExpr"],["impl Display for Expr"],["impl Display for FrameExpr"],["impl Display for IndexConst"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1304]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Freeze.js b/trait.impl/core/marker/trait.Freeze.js new file mode 100644 index 0000000..ee7f6dd --- /dev/null +++ b/trait.impl/core/marker/trait.Freeze.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl !Freeze for IPC",1,["vidformer::filter::builtin::ipc::IPC"]],["impl Freeze for Error",1,["vidformer::dve::Error"]],["impl Freeze for RangeTsFormat",1,["vidformer::dve::RangeTsFormat"]],["impl Freeze for Val",1,["vidformer::filter::Val"]],["impl Freeze for DataExpr",1,["vidformer::sir::DataExpr"]],["impl Freeze for Expr",1,["vidformer::sir::Expr"]],["impl Freeze for FrameExpr",1,["vidformer::sir::FrameExpr"]],["impl Freeze for IndexConst",1,["vidformer::sir::IndexConst"]],["impl Freeze for JsonArary",1,["vidformer::array::JsonArary"]],["impl Freeze for Annotate",1,["vidformer::filter::builtin::Annotate"]],["impl Freeze for BoundingBox",1,["vidformer::filter::builtin::BoundingBox"]],["impl Freeze for BoundingBoxBound",1,["vidformer::filter::builtin::BoundingBoxBound"]],["impl Freeze for Box",1,["vidformer::filter::builtin::Box"]],["impl Freeze for DrawBox",1,["vidformer::filter::builtin::DrawBox"]],["impl Freeze for DrawText",1,["vidformer::filter::builtin::DrawText"]],["impl Freeze for HStack",1,["vidformer::filter::builtin::HStack"]],["impl Freeze for InlineMat",1,["vidformer::filter::builtin::InlineMat"]],["impl Freeze for Pad",1,["vidformer::filter::builtin::Pad"]],["impl Freeze for PlaceholderFrame",1,["vidformer::filter::builtin::PlaceholderFrame"]],["impl Freeze for Scale",1,["vidformer::filter::builtin::Scale"]],["impl Freeze for SliceMat",1,["vidformer::filter::builtin::SliceMat"]],["impl Freeze for SliceWriteMat",1,["vidformer::filter::builtin::SliceWriteMat"]],["impl Freeze for VStack",1,["vidformer::filter::builtin::VStack"]],["impl Freeze for AddWeighted",1,["vidformer::filter::cv2::AddWeighted"]],["impl Freeze for ArrowedLine",1,["vidformer::filter::cv2::ArrowedLine"]],["impl Freeze for Circle",1,["vidformer::filter::cv2::Circle"]],["impl Freeze for Line",1,["vidformer::filter::cv2::Line"]],["impl Freeze for PutText",1,["vidformer::filter::cv2::PutText"]],["impl Freeze for Rectangle",1,["vidformer::filter::cv2::Rectangle"]],["impl Freeze for SetTo",1,["vidformer::filter::cv2::SetTo"]],["impl Freeze for Frame",1,["vidformer::filter::Frame"]],["impl Freeze for FrameType",1,["vidformer::filter::FrameType"]],["impl Freeze for Service",1,["vidformer::service::Service"]],["impl Freeze for FilterExpr",1,["vidformer::sir::FilterExpr"]],["impl Freeze for FrameSource",1,["vidformer::sir::FrameSource"]],["impl Freeze for SourceFileMeta",1,["vidformer::source::SourceFileMeta"]],["impl Freeze for SourceVideoStreamMeta",1,["vidformer::source::SourceVideoStreamMeta"]],["impl Freeze for JsonSpec",1,["vidformer::spec::JsonSpec"]],["impl Freeze for CodecDescriptor",1,["vidformer::util::CodecDescriptor"]],["impl Freeze for Config",1,["vidformer::dve::Config"]],["impl Freeze for Context",1,["vidformer::dve::Context"]],["impl Freeze for EncoderConfig",1,["vidformer::dve::EncoderConfig"]],["impl Freeze for Range",1,["vidformer::dve::Range"]],["impl Freeze for Stats",1,["vidformer::dve::Stats"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[14028]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Send.js b/trait.impl/core/marker/trait.Send.js new file mode 100644 index 0000000..e3d4e6c --- /dev/null +++ b/trait.impl/core/marker/trait.Send.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl Send for Error",1,["vidformer::dve::Error"]],["impl Send for RangeTsFormat",1,["vidformer::dve::RangeTsFormat"]],["impl Send for Val",1,["vidformer::filter::Val"]],["impl Send for DataExpr",1,["vidformer::sir::DataExpr"]],["impl Send for Expr",1,["vidformer::sir::Expr"]],["impl Send for FrameExpr",1,["vidformer::sir::FrameExpr"]],["impl Send for IndexConst",1,["vidformer::sir::IndexConst"]],["impl Send for JsonArary",1,["vidformer::array::JsonArary"]],["impl Send for Annotate",1,["vidformer::filter::builtin::Annotate"]],["impl Send for BoundingBox",1,["vidformer::filter::builtin::BoundingBox"]],["impl Send for BoundingBoxBound",1,["vidformer::filter::builtin::BoundingBoxBound"]],["impl Send for Box",1,["vidformer::filter::builtin::Box"]],["impl Send for DrawBox",1,["vidformer::filter::builtin::DrawBox"]],["impl Send for DrawText",1,["vidformer::filter::builtin::DrawText"]],["impl Send for HStack",1,["vidformer::filter::builtin::HStack"]],["impl Send for IPC",1,["vidformer::filter::builtin::ipc::IPC"]],["impl Send for InlineMat",1,["vidformer::filter::builtin::InlineMat"]],["impl Send for Pad",1,["vidformer::filter::builtin::Pad"]],["impl Send for PlaceholderFrame",1,["vidformer::filter::builtin::PlaceholderFrame"]],["impl Send for Scale",1,["vidformer::filter::builtin::Scale"]],["impl Send for SliceMat",1,["vidformer::filter::builtin::SliceMat"]],["impl Send for SliceWriteMat",1,["vidformer::filter::builtin::SliceWriteMat"]],["impl Send for VStack",1,["vidformer::filter::builtin::VStack"]],["impl Send for AddWeighted",1,["vidformer::filter::cv2::AddWeighted"]],["impl Send for ArrowedLine",1,["vidformer::filter::cv2::ArrowedLine"]],["impl Send for Circle",1,["vidformer::filter::cv2::Circle"]],["impl Send for Line",1,["vidformer::filter::cv2::Line"]],["impl Send for PutText",1,["vidformer::filter::cv2::PutText"]],["impl Send for Rectangle",1,["vidformer::filter::cv2::Rectangle"]],["impl Send for SetTo",1,["vidformer::filter::cv2::SetTo"]],["impl Send for Frame",1,["vidformer::filter::Frame"]],["impl Send for FrameType",1,["vidformer::filter::FrameType"]],["impl Send for Service",1,["vidformer::service::Service"]],["impl Send for FilterExpr",1,["vidformer::sir::FilterExpr"]],["impl Send for FrameSource",1,["vidformer::sir::FrameSource"]],["impl Send for SourceFileMeta",1,["vidformer::source::SourceFileMeta"]],["impl Send for SourceVideoStreamMeta",1,["vidformer::source::SourceVideoStreamMeta"]],["impl Send for JsonSpec",1,["vidformer::spec::JsonSpec"]],["impl Send for CodecDescriptor",1,["vidformer::util::CodecDescriptor"]],["impl Send for Config",1,["vidformer::dve::Config"]],["impl Send for Context",1,["vidformer::dve::Context"]],["impl Send for EncoderConfig",1,["vidformer::dve::EncoderConfig"]],["impl Send for Range",1,["vidformer::dve::Range"]],["impl Send for Stats",1,["vidformer::dve::Stats"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[13763]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.StructuralPartialEq.js b/trait.impl/core/marker/trait.StructuralPartialEq.js new file mode 100644 index 0000000..efc95c7 --- /dev/null +++ b/trait.impl/core/marker/trait.StructuralPartialEq.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl StructuralPartialEq for IndexConst"],["impl StructuralPartialEq for FrameType"],["impl StructuralPartialEq for FrameSource"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[963]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Sync.js b/trait.impl/core/marker/trait.Sync.js new file mode 100644 index 0000000..b61f5a4 --- /dev/null +++ b/trait.impl/core/marker/trait.Sync.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl Sync for Error",1,["vidformer::dve::Error"]],["impl Sync for RangeTsFormat",1,["vidformer::dve::RangeTsFormat"]],["impl Sync for Val",1,["vidformer::filter::Val"]],["impl Sync for DataExpr",1,["vidformer::sir::DataExpr"]],["impl Sync for Expr",1,["vidformer::sir::Expr"]],["impl Sync for FrameExpr",1,["vidformer::sir::FrameExpr"]],["impl Sync for IndexConst",1,["vidformer::sir::IndexConst"]],["impl Sync for JsonArary",1,["vidformer::array::JsonArary"]],["impl Sync for Annotate",1,["vidformer::filter::builtin::Annotate"]],["impl Sync for BoundingBox",1,["vidformer::filter::builtin::BoundingBox"]],["impl Sync for BoundingBoxBound",1,["vidformer::filter::builtin::BoundingBoxBound"]],["impl Sync for Box",1,["vidformer::filter::builtin::Box"]],["impl Sync for DrawBox",1,["vidformer::filter::builtin::DrawBox"]],["impl Sync for DrawText",1,["vidformer::filter::builtin::DrawText"]],["impl Sync for HStack",1,["vidformer::filter::builtin::HStack"]],["impl Sync for IPC",1,["vidformer::filter::builtin::ipc::IPC"]],["impl Sync for InlineMat",1,["vidformer::filter::builtin::InlineMat"]],["impl Sync for Pad",1,["vidformer::filter::builtin::Pad"]],["impl Sync for PlaceholderFrame",1,["vidformer::filter::builtin::PlaceholderFrame"]],["impl Sync for Scale",1,["vidformer::filter::builtin::Scale"]],["impl Sync for SliceMat",1,["vidformer::filter::builtin::SliceMat"]],["impl Sync for SliceWriteMat",1,["vidformer::filter::builtin::SliceWriteMat"]],["impl Sync for VStack",1,["vidformer::filter::builtin::VStack"]],["impl Sync for AddWeighted",1,["vidformer::filter::cv2::AddWeighted"]],["impl Sync for ArrowedLine",1,["vidformer::filter::cv2::ArrowedLine"]],["impl Sync for Circle",1,["vidformer::filter::cv2::Circle"]],["impl Sync for Line",1,["vidformer::filter::cv2::Line"]],["impl Sync for PutText",1,["vidformer::filter::cv2::PutText"]],["impl Sync for Rectangle",1,["vidformer::filter::cv2::Rectangle"]],["impl Sync for SetTo",1,["vidformer::filter::cv2::SetTo"]],["impl Sync for Frame",1,["vidformer::filter::Frame"]],["impl Sync for FrameType",1,["vidformer::filter::FrameType"]],["impl Sync for Service",1,["vidformer::service::Service"]],["impl Sync for FilterExpr",1,["vidformer::sir::FilterExpr"]],["impl Sync for FrameSource",1,["vidformer::sir::FrameSource"]],["impl Sync for SourceFileMeta",1,["vidformer::source::SourceFileMeta"]],["impl Sync for SourceVideoStreamMeta",1,["vidformer::source::SourceVideoStreamMeta"]],["impl Sync for JsonSpec",1,["vidformer::spec::JsonSpec"]],["impl Sync for CodecDescriptor",1,["vidformer::util::CodecDescriptor"]],["impl Sync for Config",1,["vidformer::dve::Config"]],["impl Sync for Context",1,["vidformer::dve::Context"]],["impl Sync for EncoderConfig",1,["vidformer::dve::EncoderConfig"]],["impl Sync for Range",1,["vidformer::dve::Range"]],["impl Sync for Stats",1,["vidformer::dve::Stats"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[13763]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Unpin.js b/trait.impl/core/marker/trait.Unpin.js new file mode 100644 index 0000000..b69ad06 --- /dev/null +++ b/trait.impl/core/marker/trait.Unpin.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl Unpin for Error",1,["vidformer::dve::Error"]],["impl Unpin for RangeTsFormat",1,["vidformer::dve::RangeTsFormat"]],["impl Unpin for Val",1,["vidformer::filter::Val"]],["impl Unpin for DataExpr",1,["vidformer::sir::DataExpr"]],["impl Unpin for Expr",1,["vidformer::sir::Expr"]],["impl Unpin for FrameExpr",1,["vidformer::sir::FrameExpr"]],["impl Unpin for IndexConst",1,["vidformer::sir::IndexConst"]],["impl Unpin for JsonArary",1,["vidformer::array::JsonArary"]],["impl Unpin for Annotate",1,["vidformer::filter::builtin::Annotate"]],["impl Unpin for BoundingBox",1,["vidformer::filter::builtin::BoundingBox"]],["impl Unpin for BoundingBoxBound",1,["vidformer::filter::builtin::BoundingBoxBound"]],["impl Unpin for Box",1,["vidformer::filter::builtin::Box"]],["impl Unpin for DrawBox",1,["vidformer::filter::builtin::DrawBox"]],["impl Unpin for DrawText",1,["vidformer::filter::builtin::DrawText"]],["impl Unpin for HStack",1,["vidformer::filter::builtin::HStack"]],["impl Unpin for IPC",1,["vidformer::filter::builtin::ipc::IPC"]],["impl Unpin for InlineMat",1,["vidformer::filter::builtin::InlineMat"]],["impl Unpin for Pad",1,["vidformer::filter::builtin::Pad"]],["impl Unpin for PlaceholderFrame",1,["vidformer::filter::builtin::PlaceholderFrame"]],["impl Unpin for Scale",1,["vidformer::filter::builtin::Scale"]],["impl Unpin for SliceMat",1,["vidformer::filter::builtin::SliceMat"]],["impl Unpin for SliceWriteMat",1,["vidformer::filter::builtin::SliceWriteMat"]],["impl Unpin for VStack",1,["vidformer::filter::builtin::VStack"]],["impl Unpin for AddWeighted",1,["vidformer::filter::cv2::AddWeighted"]],["impl Unpin for ArrowedLine",1,["vidformer::filter::cv2::ArrowedLine"]],["impl Unpin for Circle",1,["vidformer::filter::cv2::Circle"]],["impl Unpin for Line",1,["vidformer::filter::cv2::Line"]],["impl Unpin for PutText",1,["vidformer::filter::cv2::PutText"]],["impl Unpin for Rectangle",1,["vidformer::filter::cv2::Rectangle"]],["impl Unpin for SetTo",1,["vidformer::filter::cv2::SetTo"]],["impl Unpin for Frame",1,["vidformer::filter::Frame"]],["impl Unpin for FrameType",1,["vidformer::filter::FrameType"]],["impl Unpin for Service",1,["vidformer::service::Service"]],["impl Unpin for FilterExpr",1,["vidformer::sir::FilterExpr"]],["impl Unpin for FrameSource",1,["vidformer::sir::FrameSource"]],["impl Unpin for SourceFileMeta",1,["vidformer::source::SourceFileMeta"]],["impl Unpin for SourceVideoStreamMeta",1,["vidformer::source::SourceVideoStreamMeta"]],["impl Unpin for JsonSpec",1,["vidformer::spec::JsonSpec"]],["impl Unpin for CodecDescriptor",1,["vidformer::util::CodecDescriptor"]],["impl Unpin for Config",1,["vidformer::dve::Config"]],["impl Unpin for Context",1,["vidformer::dve::Context"]],["impl Unpin for EncoderConfig",1,["vidformer::dve::EncoderConfig"]],["impl Unpin for Range",1,["vidformer::dve::Range"]],["impl Unpin for Stats",1,["vidformer::dve::Stats"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[13895]} \ No newline at end of file diff --git a/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js b/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js new file mode 100644 index 0000000..0f26524 --- /dev/null +++ b/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl !RefUnwindSafe for IPC",1,["vidformer::filter::builtin::ipc::IPC"]],["impl !RefUnwindSafe for Context",1,["vidformer::dve::Context"]],["impl RefUnwindSafe for Error",1,["vidformer::dve::Error"]],["impl RefUnwindSafe for RangeTsFormat",1,["vidformer::dve::RangeTsFormat"]],["impl RefUnwindSafe for Val",1,["vidformer::filter::Val"]],["impl RefUnwindSafe for DataExpr",1,["vidformer::sir::DataExpr"]],["impl RefUnwindSafe for Expr",1,["vidformer::sir::Expr"]],["impl RefUnwindSafe for FrameExpr",1,["vidformer::sir::FrameExpr"]],["impl RefUnwindSafe for IndexConst",1,["vidformer::sir::IndexConst"]],["impl RefUnwindSafe for JsonArary",1,["vidformer::array::JsonArary"]],["impl RefUnwindSafe for Annotate",1,["vidformer::filter::builtin::Annotate"]],["impl RefUnwindSafe for BoundingBox",1,["vidformer::filter::builtin::BoundingBox"]],["impl RefUnwindSafe for BoundingBoxBound",1,["vidformer::filter::builtin::BoundingBoxBound"]],["impl RefUnwindSafe for Box",1,["vidformer::filter::builtin::Box"]],["impl RefUnwindSafe for DrawBox",1,["vidformer::filter::builtin::DrawBox"]],["impl RefUnwindSafe for DrawText",1,["vidformer::filter::builtin::DrawText"]],["impl RefUnwindSafe for HStack",1,["vidformer::filter::builtin::HStack"]],["impl RefUnwindSafe for InlineMat",1,["vidformer::filter::builtin::InlineMat"]],["impl RefUnwindSafe for Pad",1,["vidformer::filter::builtin::Pad"]],["impl RefUnwindSafe for PlaceholderFrame",1,["vidformer::filter::builtin::PlaceholderFrame"]],["impl RefUnwindSafe for Scale",1,["vidformer::filter::builtin::Scale"]],["impl RefUnwindSafe for SliceMat",1,["vidformer::filter::builtin::SliceMat"]],["impl RefUnwindSafe for SliceWriteMat",1,["vidformer::filter::builtin::SliceWriteMat"]],["impl RefUnwindSafe for VStack",1,["vidformer::filter::builtin::VStack"]],["impl RefUnwindSafe for AddWeighted",1,["vidformer::filter::cv2::AddWeighted"]],["impl RefUnwindSafe for ArrowedLine",1,["vidformer::filter::cv2::ArrowedLine"]],["impl RefUnwindSafe for Circle",1,["vidformer::filter::cv2::Circle"]],["impl RefUnwindSafe for Line",1,["vidformer::filter::cv2::Line"]],["impl RefUnwindSafe for PutText",1,["vidformer::filter::cv2::PutText"]],["impl RefUnwindSafe for Rectangle",1,["vidformer::filter::cv2::Rectangle"]],["impl RefUnwindSafe for SetTo",1,["vidformer::filter::cv2::SetTo"]],["impl RefUnwindSafe for Frame",1,["vidformer::filter::Frame"]],["impl RefUnwindSafe for FrameType",1,["vidformer::filter::FrameType"]],["impl RefUnwindSafe for Service",1,["vidformer::service::Service"]],["impl RefUnwindSafe for FilterExpr",1,["vidformer::sir::FilterExpr"]],["impl RefUnwindSafe for FrameSource",1,["vidformer::sir::FrameSource"]],["impl RefUnwindSafe for SourceFileMeta",1,["vidformer::source::SourceFileMeta"]],["impl RefUnwindSafe for SourceVideoStreamMeta",1,["vidformer::source::SourceVideoStreamMeta"]],["impl RefUnwindSafe for JsonSpec",1,["vidformer::spec::JsonSpec"]],["impl RefUnwindSafe for CodecDescriptor",1,["vidformer::util::CodecDescriptor"]],["impl RefUnwindSafe for Config",1,["vidformer::dve::Config"]],["impl RefUnwindSafe for EncoderConfig",1,["vidformer::dve::EncoderConfig"]],["impl RefUnwindSafe for Range",1,["vidformer::dve::Range"]],["impl RefUnwindSafe for Stats",1,["vidformer::dve::Stats"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[15965]} \ No newline at end of file diff --git a/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js b/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js new file mode 100644 index 0000000..6adb19f --- /dev/null +++ b/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl !UnwindSafe for Context",1,["vidformer::dve::Context"]],["impl UnwindSafe for Error",1,["vidformer::dve::Error"]],["impl UnwindSafe for RangeTsFormat",1,["vidformer::dve::RangeTsFormat"]],["impl UnwindSafe for Val",1,["vidformer::filter::Val"]],["impl UnwindSafe for DataExpr",1,["vidformer::sir::DataExpr"]],["impl UnwindSafe for Expr",1,["vidformer::sir::Expr"]],["impl UnwindSafe for FrameExpr",1,["vidformer::sir::FrameExpr"]],["impl UnwindSafe for IndexConst",1,["vidformer::sir::IndexConst"]],["impl UnwindSafe for JsonArary",1,["vidformer::array::JsonArary"]],["impl UnwindSafe for Annotate",1,["vidformer::filter::builtin::Annotate"]],["impl UnwindSafe for BoundingBox",1,["vidformer::filter::builtin::BoundingBox"]],["impl UnwindSafe for BoundingBoxBound",1,["vidformer::filter::builtin::BoundingBoxBound"]],["impl UnwindSafe for Box",1,["vidformer::filter::builtin::Box"]],["impl UnwindSafe for DrawBox",1,["vidformer::filter::builtin::DrawBox"]],["impl UnwindSafe for DrawText",1,["vidformer::filter::builtin::DrawText"]],["impl UnwindSafe for HStack",1,["vidformer::filter::builtin::HStack"]],["impl UnwindSafe for IPC",1,["vidformer::filter::builtin::ipc::IPC"]],["impl UnwindSafe for InlineMat",1,["vidformer::filter::builtin::InlineMat"]],["impl UnwindSafe for Pad",1,["vidformer::filter::builtin::Pad"]],["impl UnwindSafe for PlaceholderFrame",1,["vidformer::filter::builtin::PlaceholderFrame"]],["impl UnwindSafe for Scale",1,["vidformer::filter::builtin::Scale"]],["impl UnwindSafe for SliceMat",1,["vidformer::filter::builtin::SliceMat"]],["impl UnwindSafe for SliceWriteMat",1,["vidformer::filter::builtin::SliceWriteMat"]],["impl UnwindSafe for VStack",1,["vidformer::filter::builtin::VStack"]],["impl UnwindSafe for AddWeighted",1,["vidformer::filter::cv2::AddWeighted"]],["impl UnwindSafe for ArrowedLine",1,["vidformer::filter::cv2::ArrowedLine"]],["impl UnwindSafe for Circle",1,["vidformer::filter::cv2::Circle"]],["impl UnwindSafe for Line",1,["vidformer::filter::cv2::Line"]],["impl UnwindSafe for PutText",1,["vidformer::filter::cv2::PutText"]],["impl UnwindSafe for Rectangle",1,["vidformer::filter::cv2::Rectangle"]],["impl UnwindSafe for SetTo",1,["vidformer::filter::cv2::SetTo"]],["impl UnwindSafe for Frame",1,["vidformer::filter::Frame"]],["impl UnwindSafe for FrameType",1,["vidformer::filter::FrameType"]],["impl UnwindSafe for Service",1,["vidformer::service::Service"]],["impl UnwindSafe for FilterExpr",1,["vidformer::sir::FilterExpr"]],["impl UnwindSafe for FrameSource",1,["vidformer::sir::FrameSource"]],["impl UnwindSafe for SourceFileMeta",1,["vidformer::source::SourceFileMeta"]],["impl UnwindSafe for SourceVideoStreamMeta",1,["vidformer::source::SourceVideoStreamMeta"]],["impl UnwindSafe for JsonSpec",1,["vidformer::spec::JsonSpec"]],["impl UnwindSafe for CodecDescriptor",1,["vidformer::util::CodecDescriptor"]],["impl UnwindSafe for Config",1,["vidformer::dve::Config"]],["impl UnwindSafe for EncoderConfig",1,["vidformer::dve::EncoderConfig"]],["impl UnwindSafe for Range",1,["vidformer::dve::Range"]],["impl UnwindSafe for Stats",1,["vidformer::dve::Stats"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[15568]} \ No newline at end of file diff --git a/trait.impl/serde/de/trait.Deserialize.js b/trait.impl/serde/de/trait.Deserialize.js new file mode 100644 index 0000000..d6945a5 --- /dev/null +++ b/trait.impl/serde/de/trait.Deserialize.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl<'de> Deserialize<'de> for DataExpr"],["impl<'de> Deserialize<'de> for Expr"],["impl<'de> Deserialize<'de> for FrameExpr"],["impl<'de> Deserialize<'de> for IndexConst"],["impl<'de> Deserialize<'de> for JsonArary"],["impl<'de> Deserialize<'de> for BoundingBoxBound"],["impl<'de> Deserialize<'de> for Frame"],["impl<'de> Deserialize<'de> for FrameType"],["impl<'de> Deserialize<'de> for Service"],["impl<'de> Deserialize<'de> for FilterExpr"],["impl<'de> Deserialize<'de> for FrameSource"],["impl<'de> Deserialize<'de> for SourceFileMeta"],["impl<'de> Deserialize<'de> for SourceVideoStreamMeta"],["impl<'de> Deserialize<'de> for JsonSpec"],["impl<'de> Deserialize<'de> for Config"],["impl<'de> Deserialize<'de> for EncoderConfig"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[4914]} \ No newline at end of file diff --git a/trait.impl/serde/ser/trait.Serialize.js b/trait.impl/serde/ser/trait.Serialize.js new file mode 100644 index 0000000..4fcb440 --- /dev/null +++ b/trait.impl/serde/ser/trait.Serialize.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[["impl Serialize for Val"],["impl Serialize for DataExpr"],["impl Serialize for Expr"],["impl Serialize for FrameExpr"],["impl Serialize for IndexConst"],["impl Serialize for JsonArary"],["impl Serialize for Frame"],["impl Serialize for FrameType"],["impl Serialize for Service"],["impl Serialize for FilterExpr"],["impl Serialize for FrameSource"],["impl Serialize for SourceFileMeta"],["impl Serialize for SourceVideoStreamMeta"],["impl Serialize for JsonSpec"],["impl Serialize for Config"],["impl Serialize for EncoderConfig"],["impl Serialize for Stats"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[4691]} \ No newline at end of file diff --git a/trait.impl/vidformer/array/trait.Array.js b/trait.impl/vidformer/array/trait.Array.js new file mode 100644 index 0000000..64003a1 --- /dev/null +++ b/trait.impl/vidformer/array/trait.Array.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[16]} \ No newline at end of file diff --git a/trait.impl/vidformer/filter/trait.Filter.js b/trait.impl/vidformer/filter/trait.Filter.js new file mode 100644 index 0000000..64003a1 --- /dev/null +++ b/trait.impl/vidformer/filter/trait.Filter.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[16]} \ No newline at end of file diff --git a/trait.impl/vidformer/spec/trait.Spec.js b/trait.impl/vidformer/spec/trait.Spec.js new file mode 100644 index 0000000..64003a1 --- /dev/null +++ b/trait.impl/vidformer/spec/trait.Spec.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["vidformer",[]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[16]} \ No newline at end of file diff --git a/udf-filters.html b/udf-filters.html new file mode 100644 index 0000000..1397953 --- /dev/null +++ b/udf-filters.html @@ -0,0 +1,256 @@ + + + + + + User-Defined Filters - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

User-Defined Filters

+

To implement a new user-defined filter (UDF) you need to host a filter server over a UNIX Domain Socket. +The vidformer-py library makes this easy.

+

Filters take some combination of frames and data (string, int, bool) and return a single frame result. +The vidformer project uses Python-style arguments, allowing ordered and named arguments (*args and **kwargs style).

+

To do this we define a new filter class and host it:

+
import vidformer as vf
+import cv2
+
+class MyFilter(vf.UDF):
+
+    def filter(self, frame: vf.UDFFrame, name: str):
+        """Return the result frame."""
+
+        text = f"Hello, {name}!"
+
+        image = frame.data().copy()
+        cv2.putText(
+		    image,
+            text, 
+            (100,100),
+            cv2.FONT_HERSHEY_SIMPLEX,
+            1,
+            (255, 0, 0),
+            1,
+        )
+        return vf.UDFFrame(image, frame.frame_type())
+
+    def filter_type(self, frame: vf.UDFFrameType, _name: str):
+        """Returns the type of the output frame."""
+        return frame
+
+mf_udf = MyFilter("MyFilter") # name used for pretty printing
+
+my_filter = mf_udf.into_filter() # host the UDF in a subprocess, returns a vf.Filter
+
+

Now we can use our newly-created filter in specs: my_filter(some_frame, "vidformer").

+

There is a catch, UDFs currently only support rgb24 pixel formats. +So invoking my_filter will need to convert around this:

+
scale = vf.Filter('Scale')
+
+def render(t, i):
+    f = scale(tos[t], pix_fmt="rgb24", width=1280, height=720)
+    f = my_filter(f, "world")
+    f = scale(f, pix_fmt="yuv420p", width=1280, height=720)
+    return f
+
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/vidformer-py-cv2/index.html b/vidformer-py-cv2/index.html new file mode 100644 index 0000000..6e134f6 --- /dev/null +++ b/vidformer-py-cv2/index.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/vidformer-py-cv2/search.js b/vidformer-py-cv2/search.js new file mode 100644 index 0000000..0321465 --- /dev/null +++ b/vidformer-py-cv2/search.js @@ -0,0 +1,46 @@ +window.pdocSearch = (function(){ +/** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();ovidformer.cv2 is the cv2 frontend for vidformer.

\n\n
\n

\u26a0\ufe0f This module is a work in progress. See the implemented functions list.

\n
\n\n

Quick links:

\n\n\n"}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"fullname": "vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC", "modulename": "vidformer.cv2.vf_cv2", "qualname": "CAP_PROP_POS_MSEC", "kind": "variable", "doc": "

\n", "default_value": "0"}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"fullname": "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES", "modulename": "vidformer.cv2.vf_cv2", "qualname": "CAP_PROP_POS_FRAMES", "kind": "variable", "doc": "

\n", "default_value": "1"}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"fullname": "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH", "modulename": "vidformer.cv2.vf_cv2", "qualname": "CAP_PROP_FRAME_WIDTH", "kind": "variable", "doc": "

\n", "default_value": "3"}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"fullname": "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT", "modulename": "vidformer.cv2.vf_cv2", "qualname": "CAP_PROP_FRAME_HEIGHT", "kind": "variable", "doc": "

\n", "default_value": "4"}, "vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"fullname": "vidformer.cv2.vf_cv2.CAP_PROP_FPS", "modulename": "vidformer.cv2.vf_cv2", "qualname": "CAP_PROP_FPS", "kind": "variable", "doc": "

\n", "default_value": "5"}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"fullname": "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT", "modulename": "vidformer.cv2.vf_cv2", "qualname": "CAP_PROP_FRAME_COUNT", "kind": "variable", "doc": "

\n", "default_value": "7"}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"fullname": "vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX", "modulename": "vidformer.cv2.vf_cv2", "qualname": "FONT_HERSHEY_SIMPLEX", "kind": "variable", "doc": "

\n", "default_value": "0"}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"fullname": "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN", "modulename": "vidformer.cv2.vf_cv2", "qualname": "FONT_HERSHEY_PLAIN", "kind": "variable", "doc": "

\n", "default_value": "1"}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"fullname": "vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX", "modulename": "vidformer.cv2.vf_cv2", "qualname": "FONT_HERSHEY_DUPLEX", "kind": "variable", "doc": "

\n", "default_value": "2"}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"fullname": "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX", "modulename": "vidformer.cv2.vf_cv2", "qualname": "FONT_HERSHEY_COMPLEX", "kind": "variable", "doc": "

\n", "default_value": "3"}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"fullname": "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX", "modulename": "vidformer.cv2.vf_cv2", "qualname": "FONT_HERSHEY_TRIPLEX", "kind": "variable", "doc": "

\n", "default_value": "4"}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"fullname": "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL", "modulename": "vidformer.cv2.vf_cv2", "qualname": "FONT_HERSHEY_COMPLEX_SMALL", "kind": "variable", "doc": "

\n", "default_value": "5"}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"fullname": "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX", "modulename": "vidformer.cv2.vf_cv2", "qualname": "FONT_HERSHEY_SCRIPT_SIMPLEX", "kind": "variable", "doc": "

\n", "default_value": "6"}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"fullname": "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX", "modulename": "vidformer.cv2.vf_cv2", "qualname": "FONT_HERSHEY_SCRIPT_COMPLEX", "kind": "variable", "doc": "

\n", "default_value": "7"}, "vidformer.cv2.vf_cv2.FONT_ITALIC": {"fullname": "vidformer.cv2.vf_cv2.FONT_ITALIC", "modulename": "vidformer.cv2.vf_cv2", "qualname": "FONT_ITALIC", "kind": "variable", "doc": "

\n", "default_value": "16"}, "vidformer.cv2.vf_cv2.FILLED": {"fullname": "vidformer.cv2.vf_cv2.FILLED", "modulename": "vidformer.cv2.vf_cv2", "qualname": "FILLED", "kind": "variable", "doc": "

\n", "default_value": "-1"}, "vidformer.cv2.vf_cv2.LINE_4": {"fullname": "vidformer.cv2.vf_cv2.LINE_4", "modulename": "vidformer.cv2.vf_cv2", "qualname": "LINE_4", "kind": "variable", "doc": "

\n", "default_value": "4"}, "vidformer.cv2.vf_cv2.LINE_8": {"fullname": "vidformer.cv2.vf_cv2.LINE_8", "modulename": "vidformer.cv2.vf_cv2", "qualname": "LINE_8", "kind": "variable", "doc": "

\n", "default_value": "8"}, "vidformer.cv2.vf_cv2.LINE_AA": {"fullname": "vidformer.cv2.vf_cv2.LINE_AA", "modulename": "vidformer.cv2.vf_cv2", "qualname": "LINE_AA", "kind": "variable", "doc": "

\n", "default_value": "16"}, "vidformer.cv2.vf_cv2.set_cv2_server": {"fullname": "vidformer.cv2.vf_cv2.set_cv2_server", "modulename": "vidformer.cv2.vf_cv2", "qualname": "set_cv2_server", "kind": "function", "doc": "

Set the server to use for the cv2 frontend.

\n", "signature": "(server: vidformer.vf.YrdenServer):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.Frame": {"fullname": "vidformer.cv2.vf_cv2.Frame", "modulename": "vidformer.cv2.vf_cv2", "qualname": "Frame", "kind": "class", "doc": "

\n"}, "vidformer.cv2.vf_cv2.Frame.__init__": {"fullname": "vidformer.cv2.vf_cv2.Frame.__init__", "modulename": "vidformer.cv2.vf_cv2", "qualname": "Frame.__init__", "kind": "function", "doc": "

\n", "signature": "(f, fmt)"}, "vidformer.cv2.vf_cv2.Frame.shape": {"fullname": "vidformer.cv2.vf_cv2.Frame.shape", "modulename": "vidformer.cv2.vf_cv2", "qualname": "Frame.shape", "kind": "variable", "doc": "

\n"}, "vidformer.cv2.vf_cv2.Frame.numpy": {"fullname": "vidformer.cv2.vf_cv2.Frame.numpy", "modulename": "vidformer.cv2.vf_cv2", "qualname": "Frame.numpy", "kind": "function", "doc": "

Return the frame as a numpy array.

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.VideoCapture": {"fullname": "vidformer.cv2.vf_cv2.VideoCapture", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoCapture", "kind": "class", "doc": "

\n"}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"fullname": "vidformer.cv2.vf_cv2.VideoCapture.__init__", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoCapture.__init__", "kind": "function", "doc": "

\n", "signature": "(path)"}, "vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"fullname": "vidformer.cv2.vf_cv2.VideoCapture.isOpened", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoCapture.isOpened", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.VideoCapture.get": {"fullname": "vidformer.cv2.vf_cv2.VideoCapture.get", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoCapture.get", "kind": "function", "doc": "

\n", "signature": "(self, prop):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"fullname": "vidformer.cv2.vf_cv2.VideoCapture.set", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoCapture.set", "kind": "function", "doc": "

\n", "signature": "(self, prop, value):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.VideoCapture.read": {"fullname": "vidformer.cv2.vf_cv2.VideoCapture.read", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoCapture.read", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.VideoCapture.release": {"fullname": "vidformer.cv2.vf_cv2.VideoCapture.release", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoCapture.release", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.VideoWriter": {"fullname": "vidformer.cv2.vf_cv2.VideoWriter", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoWriter", "kind": "class", "doc": "

\n"}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"fullname": "vidformer.cv2.vf_cv2.VideoWriter.__init__", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoWriter.__init__", "kind": "function", "doc": "

\n", "signature": "(path, fourcc, fps, size)"}, "vidformer.cv2.vf_cv2.VideoWriter.write": {"fullname": "vidformer.cv2.vf_cv2.VideoWriter.write", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoWriter.write", "kind": "function", "doc": "

\n", "signature": "(self, frame):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"fullname": "vidformer.cv2.vf_cv2.VideoWriter.release", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoWriter.release", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"fullname": "vidformer.cv2.vf_cv2.VideoWriter.spec", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoWriter.spec", "kind": "function", "doc": "

\n", "signature": "(self) -> vidformer.vf.Spec:", "funcdef": "def"}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc": {"fullname": "vidformer.cv2.vf_cv2.VideoWriter_fourcc", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoWriter_fourcc", "kind": "class", "doc": "

\n"}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"fullname": "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__", "modulename": "vidformer.cv2.vf_cv2", "qualname": "VideoWriter_fourcc.__init__", "kind": "function", "doc": "

\n", "signature": "(*args)"}, "vidformer.cv2.vf_cv2.frameify": {"fullname": "vidformer.cv2.vf_cv2.frameify", "modulename": "vidformer.cv2.vf_cv2", "qualname": "frameify", "kind": "function", "doc": "

Turn an object (e.g., ndarray) into a Frame.

\n", "signature": "(obj, field_name=None):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.imread": {"fullname": "vidformer.cv2.vf_cv2.imread", "modulename": "vidformer.cv2.vf_cv2", "qualname": "imread", "kind": "function", "doc": "

\n", "signature": "(path, *args):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.imwrite": {"fullname": "vidformer.cv2.vf_cv2.imwrite", "modulename": "vidformer.cv2.vf_cv2", "qualname": "imwrite", "kind": "function", "doc": "

\n", "signature": "(path, img, *args):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.vidplay": {"fullname": "vidformer.cv2.vf_cv2.vidplay", "modulename": "vidformer.cv2.vf_cv2", "qualname": "vidplay", "kind": "function", "doc": "

Play a vidformer video specification.

\n\n

Args:\n video: one of [vidformer.Spec, vidformer.Source, vidformer.cv2.VideoWriter]

\n", "signature": "(video, *args, **kwargs):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.rectangle": {"fullname": "vidformer.cv2.vf_cv2.rectangle", "modulename": "vidformer.cv2.vf_cv2", "qualname": "rectangle", "kind": "function", "doc": "

cv.rectangle( img, pt1, pt2, color[, thickness[, lineType[, shift]]] )

\n", "signature": "(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.putText": {"fullname": "vidformer.cv2.vf_cv2.putText", "modulename": "vidformer.cv2.vf_cv2", "qualname": "putText", "kind": "function", "doc": "

cv.putText( img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]] )

\n", "signature": "(\timg,\ttext,\torg,\tfontFace,\tfontScale,\tcolor,\tthickness=None,\tlineType=None,\tbottomLeftOrigin=None):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.arrowedLine": {"fullname": "vidformer.cv2.vf_cv2.arrowedLine", "modulename": "vidformer.cv2.vf_cv2", "qualname": "arrowedLine", "kind": "function", "doc": "

cv.arrowedLine( img, pt1, pt2, color[, thickness[, line_type[, shift[, tipLength]]]] )

\n", "signature": "(\timg,\tpt1,\tpt2,\tcolor,\tthickness=None,\tline_type=None,\tshift=None,\ttipLength=None):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.line": {"fullname": "vidformer.cv2.vf_cv2.line", "modulename": "vidformer.cv2.vf_cv2", "qualname": "line", "kind": "function", "doc": "

\n", "signature": "(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.circle": {"fullname": "vidformer.cv2.vf_cv2.circle", "modulename": "vidformer.cv2.vf_cv2", "qualname": "circle", "kind": "function", "doc": "

\n", "signature": "(\timg,\tcenter,\tradius,\tcolor,\tthickness=None,\tlineType=None,\tshift=None):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"fullname": "vidformer.cv2.vf_cv2.getFontScaleFromHeight", "modulename": "vidformer.cv2.vf_cv2", "qualname": "getFontScaleFromHeight", "kind": "function", "doc": "

cv.getFontScaleFromHeight( fontFace, pixelHeight[, thickness] )

\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.getTextSize": {"fullname": "vidformer.cv2.vf_cv2.getTextSize", "modulename": "vidformer.cv2.vf_cv2", "qualname": "getTextSize", "kind": "function", "doc": "

cv.getTextSize( text, fontFace, fontScale, thickness )

\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.addWeighted": {"fullname": "vidformer.cv2.vf_cv2.addWeighted", "modulename": "vidformer.cv2.vf_cv2", "qualname": "addWeighted", "kind": "function", "doc": "

cv.addWeighted( src1, alpha, src2, beta, gamma[, dst[, dtype]] ) -> dst

\n", "signature": "(src1, alpha, src2, beta, gamma, dst=None, dtype=-1):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.clipLine": {"fullname": "vidformer.cv2.vf_cv2.clipLine", "modulename": "vidformer.cv2.vf_cv2", "qualname": "clipLine", "kind": "function", "doc": "

\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.drawContours": {"fullname": "vidformer.cv2.vf_cv2.drawContours", "modulename": "vidformer.cv2.vf_cv2", "qualname": "drawContours", "kind": "function", "doc": "

\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.drawMarker": {"fullname": "vidformer.cv2.vf_cv2.drawMarker", "modulename": "vidformer.cv2.vf_cv2", "qualname": "drawMarker", "kind": "function", "doc": "

\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.ellipse": {"fullname": "vidformer.cv2.vf_cv2.ellipse", "modulename": "vidformer.cv2.vf_cv2", "qualname": "ellipse", "kind": "function", "doc": "

\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.ellipse2Poly": {"fullname": "vidformer.cv2.vf_cv2.ellipse2Poly", "modulename": "vidformer.cv2.vf_cv2", "qualname": "ellipse2Poly", "kind": "function", "doc": "

\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.fillConvexPoly": {"fullname": "vidformer.cv2.vf_cv2.fillConvexPoly", "modulename": "vidformer.cv2.vf_cv2", "qualname": "fillConvexPoly", "kind": "function", "doc": "

\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.fillPoly": {"fullname": "vidformer.cv2.vf_cv2.fillPoly", "modulename": "vidformer.cv2.vf_cv2", "qualname": "fillPoly", "kind": "function", "doc": "

\n", "signature": "(*args, **kwargs):", "funcdef": "def"}, "vidformer.cv2.vf_cv2.polylines": {"fullname": "vidformer.cv2.vf_cv2.polylines", "modulename": "vidformer.cv2.vf_cv2", "qualname": "polylines", "kind": "function", "doc": "

\n", "signature": "(*args, **kwargs):", "funcdef": "def"}}, "docInfo": {"vidformer.cv2.vf_cv2": {"qualname": 0, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 74}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"qualname": 4, "fullname": 8, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"qualname": 4, "fullname": 8, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"qualname": 4, "fullname": 8, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"qualname": 4, "fullname": 8, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"qualname": 3, "fullname": 7, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"qualname": 4, "fullname": 8, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"qualname": 3, "fullname": 7, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"qualname": 3, "fullname": 7, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"qualname": 3, "fullname": 7, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"qualname": 3, "fullname": 7, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"qualname": 3, "fullname": 7, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"qualname": 4, "fullname": 8, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"qualname": 4, "fullname": 8, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"qualname": 4, "fullname": 8, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.FONT_ITALIC": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.FILLED": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 2, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.LINE_4": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.LINE_8": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.LINE_AA": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.set_cv2_server": {"qualname": 3, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 26, "bases": 0, "doc": 12}, "vidformer.cv2.vf_cv2.Frame": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.Frame.__init__": {"qualname": 3, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.Frame.shape": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.Frame.numpy": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 10}, "vidformer.cv2.vf_cv2.VideoCapture": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"qualname": 3, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 9, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoCapture.get": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 16, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 21, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoCapture.read": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoCapture.release": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoWriter": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"qualname": 3, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 24, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoWriter.write": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 16, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 24, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc": {"qualname": 2, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"qualname": 4, "fullname": 8, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.frameify": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 22, "bases": 0, "doc": 12}, "vidformer.cv2.vf_cv2.imread": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 18, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.imwrite": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 23, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.vidplay": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 25, "bases": 0, "doc": 21}, "vidformer.cv2.vf_cv2.rectangle": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 56, "bases": 0, "doc": 12}, "vidformer.cv2.vf_cv2.putText": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 75, "bases": 0, "doc": 14}, "vidformer.cv2.vf_cv2.arrowedLine": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 75, "bases": 0, "doc": 14}, "vidformer.cv2.vf_cv2.line": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 56, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.circle": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 63, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 8}, "vidformer.cv2.vf_cv2.getTextSize": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 9}, "vidformer.cv2.vf_cv2.addWeighted": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 51, "bases": 0, "doc": 13}, "vidformer.cv2.vf_cv2.clipLine": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.drawContours": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.drawMarker": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.ellipse": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.ellipse2Poly": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.fillConvexPoly": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.fillPoly": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 3}, "vidformer.cv2.vf_cv2.polylines": {"qualname": 1, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 3}}, "length": 59, "save": true}, "index": {"qualname": {"root": {"4": {"docs": {"vidformer.cv2.vf_cv2.LINE_4": {"tf": 1}}, "df": 1}, "8": {"docs": {"vidformer.cv2.vf_cv2.LINE_8": {"tf": 1}}, "df": 1}, "docs": {"vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1}}, "df": 4, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "p": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1}}, "df": 6}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1}}, "df": 1}}}, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1}}, "df": 3}}}}}}, "v": {"2": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}, "i": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.circle": {"tf": 1}}, "df": 1}}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.clipLine": {"tf": 1}}, "df": 1}}}}}}}}, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1}}, "df": 6}}}, "o": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1}}, "df": 2}, "l": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.polylines": {"tf": 1}}, "df": 1}}}}}}}}, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"tf": 1}}, "df": 1}}}}, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}}, "df": 1}}}}}}}, "m": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1}}, "df": 1}}}}, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.shape": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}}, "df": 7, "s": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1}}, "df": 1}, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1}}}}}}}, "p": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"tf": 1}}, "df": 1}}, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_ITALIC": {"tf": 1}}, "df": 9}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter_fourcc": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1}}, "df": 2}}}}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.FILLED": {"tf": 1}}, "df": 1}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.fillConvexPoly": {"tf": 1}}, "df": 1}}}}}}}}}}, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.fillPoly": {"tf": 1}}, "df": 1}}}}}}}}, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1}}, "df": 1}}}}, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter.write": {"tf": 1}}, "df": 1}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1}}, "df": 1}}}}, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1}}, "df": 8}}}}}}}, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1}}, "df": 2}}}}}}, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1}}, "df": 1}}}}, "c": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1}}, "df": 2}}}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 1}}, "df": 2}, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}}, "df": 1}}}}}, "h": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.Frame.shape": {"tf": 1}}, "df": 1}}}}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"tf": 1}}, "df": 1}}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.drawContours": {"tf": 1}}, "df": 1}}}}}}}}, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "k": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.drawMarker": {"tf": 1}}, "df": 1}}}}}}}}}}, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"tf": 1}}, "df": 1}}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.cv2.vf_cv2.FONT_ITALIC": {"tf": 1}}, "df": 1}}}}}, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1}}, "df": 4}}}, "s": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"tf": 1}}, "df": 1}}}}}}}, "m": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.imread": {"tf": 1}}, "df": 1}}}}, "w": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.imwrite": {"tf": 1}}, "df": 1}}}}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.LINE_4": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_8": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_AA": {"tf": 1}, "vidformer.cv2.vf_cv2.line": {"tf": 1}}, "df": 4}}}}, "a": {"docs": {}, "df": 0, "a": {"docs": {"vidformer.cv2.vf_cv2.LINE_AA": {"tf": 1}}, "df": 1}, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 1}}}}}}}}}}, "d": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}}}}}}}}}}, "n": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}}, "df": 1}}}}}, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.get": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.read": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.release": {"tf": 1}}, "df": 7}}}}}}}, "w": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.write": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1}}, "df": 7}}}}}}}}, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 1}}}}}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture.get": {"tf": 1}}, "df": 1, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}}, "df": 1}}}}}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture.read": {"tf": 1}}, "df": 1}}, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture.release": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"tf": 1}}, "df": 2}}}}}, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}}, "df": 1}}}}}}}}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"2": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.ellipse2Poly": {"tf": 1}}, "df": 1}}}}}, "docs": {"vidformer.cv2.vf_cv2.ellipse": {"tf": 1}}, "df": 1}}}}}}}}}, "fullname": {"root": {"4": {"docs": {"vidformer.cv2.vf_cv2.LINE_4": {"tf": 1}}, "df": 1}, "8": {"docs": {"vidformer.cv2.vf_cv2.LINE_8": {"tf": 1}}, "df": 1}, "docs": {"vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1}}, "df": 4, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_ITALIC": {"tf": 1}, "vidformer.cv2.vf_cv2.FILLED": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_4": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_8": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_AA": {"tf": 1}, "vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.shape": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.get": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.read": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.release": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.write": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.frameify": {"tf": 1}, "vidformer.cv2.vf_cv2.imread": {"tf": 1}, "vidformer.cv2.vf_cv2.imwrite": {"tf": 1}, "vidformer.cv2.vf_cv2.vidplay": {"tf": 1}, "vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}, "vidformer.cv2.vf_cv2.line": {"tf": 1}, "vidformer.cv2.vf_cv2.circle": {"tf": 1}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}, "vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}, "vidformer.cv2.vf_cv2.clipLine": {"tf": 1}, "vidformer.cv2.vf_cv2.drawContours": {"tf": 1}, "vidformer.cv2.vf_cv2.drawMarker": {"tf": 1}, "vidformer.cv2.vf_cv2.ellipse": {"tf": 1}, "vidformer.cv2.vf_cv2.ellipse2Poly": {"tf": 1}, "vidformer.cv2.vf_cv2.fillConvexPoly": {"tf": 1}, "vidformer.cv2.vf_cv2.fillPoly": {"tf": 1}, "vidformer.cv2.vf_cv2.polylines": {"tf": 1}}, "df": 59}}}}}}, "e": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.get": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.read": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.release": {"tf": 1}}, "df": 7}}}}}}}, "w": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.write": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1}}, "df": 7}}}}}}}}, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 1}}}}}}, "f": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_ITALIC": {"tf": 1}, "vidformer.cv2.vf_cv2.FILLED": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_4": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_8": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_AA": {"tf": 1}, "vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.shape": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.get": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.read": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.release": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.write": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.frameify": {"tf": 1}, "vidformer.cv2.vf_cv2.imread": {"tf": 1}, "vidformer.cv2.vf_cv2.imwrite": {"tf": 1}, "vidformer.cv2.vf_cv2.vidplay": {"tf": 1}, "vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}, "vidformer.cv2.vf_cv2.line": {"tf": 1}, "vidformer.cv2.vf_cv2.circle": {"tf": 1}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}, "vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}, "vidformer.cv2.vf_cv2.clipLine": {"tf": 1}, "vidformer.cv2.vf_cv2.drawContours": {"tf": 1}, "vidformer.cv2.vf_cv2.drawMarker": {"tf": 1}, "vidformer.cv2.vf_cv2.ellipse": {"tf": 1}, "vidformer.cv2.vf_cv2.ellipse2Poly": {"tf": 1}, "vidformer.cv2.vf_cv2.fillConvexPoly": {"tf": 1}, "vidformer.cv2.vf_cv2.fillPoly": {"tf": 1}, "vidformer.cv2.vf_cv2.polylines": {"tf": 1}}, "df": 59}}, "c": {"docs": {}, "df": 0, "v": {"2": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.FONT_ITALIC": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.FILLED": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.LINE_4": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.LINE_8": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.LINE_AA": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.Frame": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.Frame.shape": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoCapture": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoCapture.get": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoCapture.read": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoCapture.release": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoWriter": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoWriter.write": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.frameify": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.imread": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.imwrite": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.vidplay": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.rectangle": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.putText": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.line": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.circle": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.addWeighted": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.clipLine": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.drawContours": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.drawMarker": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.ellipse": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.ellipse2Poly": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.fillConvexPoly": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.fillPoly": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.polylines": {"tf": 1.4142135623730951}}, "df": 59}, "docs": {}, "df": 0}, "a": {"docs": {}, "df": 0, "p": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1}}, "df": 6}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1}}, "df": 1}}}, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1}}, "df": 3}}}}}}, "i": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.circle": {"tf": 1}}, "df": 1}}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.clipLine": {"tf": 1}}, "df": 1}}}}}}}}, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1}}, "df": 6}}}, "o": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1}}, "df": 2}, "l": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.polylines": {"tf": 1}}, "df": 1}}}}}}}}, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"tf": 1}}, "df": 1}}}}, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}}, "df": 1}}}}}}}, "m": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1}}, "df": 1}}}}, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.shape": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}}, "df": 7, "s": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1}}, "df": 1}, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1}}}}}}}, "p": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"tf": 1}}, "df": 1}}, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_ITALIC": {"tf": 1}}, "df": 9}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter_fourcc": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1}}, "df": 2}}}}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.FILLED": {"tf": 1}}, "df": 1}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.fillConvexPoly": {"tf": 1}}, "df": 1}}}}}}}}}}, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.fillPoly": {"tf": 1}}, "df": 1}}}}}}}}, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1}}, "df": 1}}}}, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter.write": {"tf": 1}}, "df": 1}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1}}, "df": 1}}}}, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1}}, "df": 8}}}}}}}, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1}}, "df": 2}}}}}}, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1}}, "df": 1}}}}, "c": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1}}, "df": 2}}}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 1}}, "df": 2}, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}}, "df": 1}}}}}, "h": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.Frame.shape": {"tf": 1}}, "df": 1}}}}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"tf": 1}}, "df": 1}}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.drawContours": {"tf": 1}}, "df": 1}}}}}}}}, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "k": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.drawMarker": {"tf": 1}}, "df": 1}}}}}}}}}}, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"tf": 1}}, "df": 1}}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.cv2.vf_cv2.FONT_ITALIC": {"tf": 1}}, "df": 1}}}}}, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1}}, "df": 4}}}, "s": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"tf": 1}}, "df": 1}}}}}}}, "m": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.imread": {"tf": 1}}, "df": 1}}}}, "w": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.imwrite": {"tf": 1}}, "df": 1}}}}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.LINE_4": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_8": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_AA": {"tf": 1}, "vidformer.cv2.vf_cv2.line": {"tf": 1}}, "df": 4}}}}, "a": {"docs": {}, "df": 0, "a": {"docs": {"vidformer.cv2.vf_cv2.LINE_AA": {"tf": 1}}, "df": 1}, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 1}}}}}}}}}}, "d": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}}}}}}}}}}, "n": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}}, "df": 1}}}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture.get": {"tf": 1}}, "df": 1, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}}, "df": 1}}}}}}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture.read": {"tf": 1}}, "df": 1}}, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture.release": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"tf": 1}}, "df": 2}}}}}, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}}, "df": 1}}}}}}}}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"2": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.ellipse2Poly": {"tf": 1}}, "df": 1}}}}}, "docs": {"vidformer.cv2.vf_cv2.ellipse": {"tf": 1}}, "df": 1}}}}}}}}}, "annotation": {"root": {"docs": {}, "df": 0}}, "default_value": {"root": {"0": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"tf": 1}}, "df": 2}, "1": {"6": {"docs": {"vidformer.cv2.vf_cv2.FONT_ITALIC": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_AA": {"tf": 1}}, "df": 2}, "docs": {"vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"tf": 1}, "vidformer.cv2.vf_cv2.FILLED": {"tf": 1}}, "df": 3}, "2": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"tf": 1}}, "df": 1}, "3": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"tf": 1}}, "df": 2}, "4": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"tf": 1}, "vidformer.cv2.vf_cv2.LINE_4": {"tf": 1}}, "df": 3}, "5": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1}}, "df": 2}, "6": {"docs": {"vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1}}, "df": 1}, "7": {"docs": {"vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1}}, "df": 2}, "8": {"docs": {"vidformer.cv2.vf_cv2.LINE_8": {"tf": 1}}, "df": 1}, "docs": {"vidformer.cv2.vf_cv2.FILLED": {"tf": 1}}, "df": 1}}, "signature": {"root": {"1": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}, "docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 4.69041575982343}, "vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 3.4641016151377544}, "vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 3.1622776601683795}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 2.8284271247461903}, "vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"tf": 3.1622776601683795}, "vidformer.cv2.vf_cv2.VideoCapture.get": {"tf": 3.7416573867739413}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 4.242640687119285}, "vidformer.cv2.vf_cv2.VideoCapture.read": {"tf": 3.1622776601683795}, "vidformer.cv2.vf_cv2.VideoCapture.release": {"tf": 3.1622776601683795}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 4.47213595499958}, "vidformer.cv2.vf_cv2.VideoWriter.write": {"tf": 3.7416573867739413}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"tf": 3.1622776601683795}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 4.47213595499958}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 3.1622776601683795}, "vidformer.cv2.vf_cv2.frameify": {"tf": 4.242640687119285}, "vidformer.cv2.vf_cv2.imread": {"tf": 4}, "vidformer.cv2.vf_cv2.imwrite": {"tf": 4.47213595499958}, "vidformer.cv2.vf_cv2.vidplay": {"tf": 4.69041575982343}, "vidformer.cv2.vf_cv2.rectangle": {"tf": 6.782329983125268}, "vidformer.cv2.vf_cv2.putText": {"tf": 7.937253933193772}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 7.874007874011811}, "vidformer.cv2.vf_cv2.line": {"tf": 6.782329983125268}, "vidformer.cv2.vf_cv2.circle": {"tf": 7.280109889280518}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 4.242640687119285}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 4.242640687119285}, "vidformer.cv2.vf_cv2.addWeighted": {"tf": 6.48074069840786}, "vidformer.cv2.vf_cv2.clipLine": {"tf": 4.242640687119285}, "vidformer.cv2.vf_cv2.drawContours": {"tf": 4.242640687119285}, "vidformer.cv2.vf_cv2.drawMarker": {"tf": 4.242640687119285}, "vidformer.cv2.vf_cv2.ellipse": {"tf": 4.242640687119285}, "vidformer.cv2.vf_cv2.ellipse2Poly": {"tf": 4.242640687119285}, "vidformer.cv2.vf_cv2.fillConvexPoly": {"tf": 4.242640687119285}, "vidformer.cv2.vf_cv2.fillPoly": {"tf": 4.242640687119285}, "vidformer.cv2.vf_cv2.polylines": {"tf": 4.242640687119285}}, "df": 34, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}}, "df": 1}}}}, "l": {"docs": {}, "df": 0, "f": {"docs": {"vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.get": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.read": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.release": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.write": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1}}, "df": 9}}}, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}}, "df": 1}}}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1}}, "df": 1}}}, "h": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}, "vidformer.cv2.vf_cv2.line": {"tf": 1}, "vidformer.cv2.vf_cv2.circle": {"tf": 1}}, "df": 4}}}}, "r": {"docs": {}, "df": 0, "c": {"1": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}, "2": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}}}, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1}}, "df": 2}}}}}}, "e": {"docs": {}, "df": 0, "o": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 1}}}}, "f": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1}}, "df": 2}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 1}}, "df": 1}}}}}, "y": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}}, "df": 1}}}}}}}}}}}, "f": {"docs": {"vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1}}, "df": 1, "m": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1}}, "df": 1}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}}, "df": 1}}}}, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}}, "df": 1}}}}, "s": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}}, "df": 1}}}}}}}}, "p": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}}, "df": 1}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter.write": {"tf": 1}}, "df": 1}}}}, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1}}}}}, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.imread": {"tf": 1}, "vidformer.cv2.vf_cv2.imwrite": {"tf": 1}}, "df": 4}}}, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {"vidformer.cv2.vf_cv2.VideoCapture.get": {"tf": 1}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 1}}, "df": 2}}}, "t": {"1": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}, "vidformer.cv2.vf_cv2.line": {"tf": 1}}, "df": 3}, "2": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}, "vidformer.cv2.vf_cv2.line": {"tf": 1}}, "df": 3}, "docs": {}, "df": 0}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1}, "vidformer.cv2.vf_cv2.imread": {"tf": 1}, "vidformer.cv2.vf_cv2.imwrite": {"tf": 1}, "vidformer.cv2.vf_cv2.vidplay": {"tf": 1}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}, "vidformer.cv2.vf_cv2.clipLine": {"tf": 1}, "vidformer.cv2.vf_cv2.drawContours": {"tf": 1}, "vidformer.cv2.vf_cv2.drawMarker": {"tf": 1}, "vidformer.cv2.vf_cv2.ellipse": {"tf": 1}, "vidformer.cv2.vf_cv2.ellipse2Poly": {"tf": 1}, "vidformer.cv2.vf_cv2.fillConvexPoly": {"tf": 1}, "vidformer.cv2.vf_cv2.fillPoly": {"tf": 1}, "vidformer.cv2.vf_cv2.polylines": {"tf": 1}}, "df": 14}}}, "l": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "a": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}}}}, "o": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "j": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1}}, "r": {"docs": {}, "df": 0, "g": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}}, "df": 1}}}, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}, "vidformer.cv2.vf_cv2.rectangle": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.putText": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 2}, "vidformer.cv2.vf_cv2.line": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.circle": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 7}}}}, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "g": {"docs": {"vidformer.cv2.vf_cv2.imwrite": {"tf": 1}, "vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}, "vidformer.cv2.vf_cv2.line": {"tf": 1}, "vidformer.cv2.vf_cv2.circle": {"tf": 1}}, "df": 6}}}, "k": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}, "vidformer.cv2.vf_cv2.clipLine": {"tf": 1}, "vidformer.cv2.vf_cv2.drawContours": {"tf": 1}, "vidformer.cv2.vf_cv2.drawMarker": {"tf": 1}, "vidformer.cv2.vf_cv2.ellipse": {"tf": 1}, "vidformer.cv2.vf_cv2.ellipse2Poly": {"tf": 1}, "vidformer.cv2.vf_cv2.fillConvexPoly": {"tf": 1}, "vidformer.cv2.vf_cv2.fillPoly": {"tf": 1}, "vidformer.cv2.vf_cv2.polylines": {"tf": 1}}, "df": 11}}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}, "vidformer.cv2.vf_cv2.line": {"tf": 1}, "vidformer.cv2.vf_cv2.circle": {"tf": 1}}, "df": 5}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.circle": {"tf": 1}}, "df": 1}}}}}}, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}, "vidformer.cv2.vf_cv2.line": {"tf": 1}, "vidformer.cv2.vf_cv2.circle": {"tf": 1}}, "df": 5}}}}}}}}, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}}, "df": 1}}}, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 1}}}}}}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 1, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.line": {"tf": 1}, "vidformer.cv2.vf_cv2.circle": {"tf": 1}}, "df": 4}}}}}}}}, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.circle": {"tf": 1}}, "df": 1}}}}}}, "g": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}}}}, "d": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}}}}}}, "bases": {"root": {"docs": {}, "df": 0}}, "doc": {"root": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 6.557438524302}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_MSEC": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.CAP_PROP_POS_FRAMES": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_WIDTH": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_HEIGHT": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.CAP_PROP_FPS": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.CAP_PROP_FRAME_COUNT": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SIMPLEX": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_PLAIN": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_DUPLEX": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_TRIPLEX": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_COMPLEX_SMALL": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_SIMPLEX": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.FONT_HERSHEY_SCRIPT_COMPLEX": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.FONT_ITALIC": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.FILLED": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.LINE_4": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.LINE_8": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.LINE_AA": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.Frame": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.Frame.__init__": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.Frame.shape": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoCapture": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoCapture.__init__": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoCapture.isOpened": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoCapture.get": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoCapture.set": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoCapture.read": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoCapture.release": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoWriter": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoWriter.__init__": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoWriter.write": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoWriter.release": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoWriter.spec": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.VideoWriter_fourcc.__init__": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.frameify": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.imread": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.imwrite": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.vidplay": {"tf": 2.23606797749979}, "vidformer.cv2.vf_cv2.rectangle": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.putText": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.line": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.circle": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.addWeighted": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.clipLine": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.drawContours": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.drawMarker": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.ellipse": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.ellipse2Poly": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.fillConvexPoly": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.fillPoly": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.polylines": {"tf": 1.7320508075688772}}, "df": 59, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 2}, "vidformer.cv2.vf_cv2.vidplay": {"tf": 2}}, "df": 2}}}}}}, "e": {"docs": {}, "df": 0, "o": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1.4142135623730951}}, "df": 1, "w": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 1}}}}}}}}}}}, "c": {"docs": {}, "df": 0, "v": {"2": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1.7320508075688772}, "vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}, "vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 3}, "docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}, "vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 6}, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 3}}}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1.4142135623730951}}, "df": 1}, "n": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1, "t": {"docs": {}, "df": 0, "o": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1}}}, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}}}}}}}}}, "g": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 3}}}, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1.4142135623730951}, "vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}}, "df": 3}, "i": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}, "c": {"docs": {}, "df": 0, "k": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}}, "df": 5}}}}}}}}, "o": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}}, "df": 1}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}}, "df": 2}}}, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 1}}}}}}}}}, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}, "vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}}, "df": 2}}}}}}, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}, "vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 2}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}, "vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}}, "df": 2}, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}}, "df": 3}}}}, "s": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}, "vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}}, "df": 2}}}}}}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}}}}}}}}}, "m": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}}}}}}, "a": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}, "vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}, "vidformer.cv2.vf_cv2.frameify": {"tf": 1}, "vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 4, "s": {"docs": {"vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}}, "df": 1}, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}}, "df": 1}}, "o": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 1}}}}}}}}}, "g": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 1}}}, "n": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1}, "d": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}}}}}}}}}, "l": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "a": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}}}}, "w": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "k": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}}}}, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}}}}}}}, "y": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1, "p": {"docs": {}, "df": 0, "i": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}}}, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 1}}}, "t": {"1": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 2}, "2": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 2}, "docs": {}, "df": 0}, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}}, "df": 1}}}}}}, "i": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1}}, "df": 1}}}}}}}}}}}, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}, "t": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}}, "df": 1}, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}}, "df": 1}}}}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}, "vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 2}}}}}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 1, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "h": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 2}}}}, "r": {"docs": {}, "df": 0, "c": {"1": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}, "2": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}}, "n": {"docs": {}, "df": 0, "k": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}}, "e": {"docs": {"vidformer.cv2.vf_cv2.arrowedLine": {"tf": 1}}, "df": 1, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}, "vidformer.cv2.vf_cv2.putText": {"tf": 1}}, "df": 2}}}}}}}}, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1}}, "df": 1}}}}}, "d": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.cv2.vf_cv2": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1.4142135623730951}}, "df": 1}}, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}}}}, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.set_cv2_server": {"tf": 1}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}}, "df": 1}}}}, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.rectangle": {"tf": 1}}, "df": 1}}}}}}}}}, "n": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.Frame.numpy": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1}}}}}}}, "o": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "j": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1}}}}}, "n": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 1}}, "f": {"docs": {"vidformer.cv2.vf_cv2.vidplay": {"tf": 1}}, "df": 1}, "r": {"docs": {}, "df": 0, "g": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}}, "df": 1}}}, "e": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1}, "g": {"docs": {"vidformer.cv2.vf_cv2.frameify": {"tf": 1}}, "df": 1, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.cv2.vf_cv2.getFontScaleFromHeight": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "z": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.cv2.vf_cv2.getTextSize": {"tf": 1}}, "df": 1}}}}}}}}}}, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}}}}, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.cv2.vf_cv2.putText": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"vidformer.cv2.vf_cv2.addWeighted": {"tf": 1}}, "df": 1}}}}}}}, "pipeline": ["trimmer"], "_isPrebuiltIndex": true}; + + // mirrored in build-search-index.js (part 1) + // Also split on html tags. this is a cheap heuristic, but good enough. + elasticlunr.tokenizer.setSeperator(/[\s\-.;&_'"=,()]+|<[^>]*>/); + + let searchIndex; + if (docs._isPrebuiltIndex) { + console.info("using precompiled search index"); + searchIndex = elasticlunr.Index.load(docs); + } else { + console.time("building search index"); + // mirrored in build-search-index.js (part 2) + searchIndex = elasticlunr(function () { + this.pipeline.remove(elasticlunr.stemmer); + this.pipeline.remove(elasticlunr.stopWordFilter); + this.addField("qualname"); + this.addField("fullname"); + this.addField("annotation"); + this.addField("default_value"); + this.addField("signature"); + this.addField("bases"); + this.addField("doc"); + this.setRef("fullname"); + }); + for (let doc of docs) { + searchIndex.addDoc(doc); + } + console.timeEnd("building search index"); + } + + return (term) => searchIndex.search(term, { + fields: { + qualname: {boost: 4}, + fullname: {boost: 2}, + annotation: {boost: 2}, + default_value: {boost: 2}, + signature: {boost: 2}, + bases: {boost: 2}, + doc: {boost: 1}, + }, + expand: true + }); +})(); \ No newline at end of file diff --git a/vidformer-py-cv2/vidformer/cv2/vf_cv2.html b/vidformer-py-cv2/vidformer/cv2/vf_cv2.html new file mode 100644 index 0000000..8d5c5d6 --- /dev/null +++ b/vidformer-py-cv2/vidformer/cv2/vf_cv2.html @@ -0,0 +1,2449 @@ + + + + + + + vidformer.cv2.vf_cv2 API documentation + + + + + + + + + +
+
+

+vidformer.cv2.vf_cv2

+ +

vidformer.cv2 is the cv2 frontend for vidformer.

+ +
+

⚠️ This module is a work in progress. See the implemented functions list.

+
+ +

Quick links:

+ + +
+ + + + + +
  1"""
+  2vidformer.cv2 is the cv2 frontend for [vidformer](https://github.com/ixlab/vidformer).
+  3
+  4> ⚠️ This module is a work in progress. See the [implemented functions list](https://ixlab.github.io/vidformer/opencv-filters.html).
+  5
+  6**Quick links:**
+  7* [📦 PyPI](https://pypi.org/project/vidformer/)
+  8* [📘 Documentation - vidformer-py](https://ixlab.github.io/vidformer/vidformer-py/)
+  9* [📘 Documentation - vidformer.cv2](https://ixlab.github.io/vidformer/vidformer-py-cv2/)
+ 10* [🧑‍💻 Source Code](https://github.com/ixlab/vidformer/tree/main/vidformer-py/)
+ 11"""
+ 12
+ 13from .. import vf
+ 14
+ 15try:
+ 16    import cv2 as _opencv2
+ 17except:
+ 18    _opencv2 = None
+ 19
+ 20import numpy as np
+ 21
+ 22import uuid
+ 23from fractions import Fraction
+ 24from bisect import bisect_right
+ 25
+ 26CAP_PROP_POS_MSEC = 0
+ 27CAP_PROP_POS_FRAMES = 1
+ 28CAP_PROP_FRAME_WIDTH = 3
+ 29CAP_PROP_FRAME_HEIGHT = 4
+ 30CAP_PROP_FPS = 5
+ 31CAP_PROP_FRAME_COUNT = 7
+ 32
+ 33FONT_HERSHEY_SIMPLEX = 0
+ 34FONT_HERSHEY_PLAIN = 1
+ 35FONT_HERSHEY_DUPLEX = 2
+ 36FONT_HERSHEY_COMPLEX = 3
+ 37FONT_HERSHEY_TRIPLEX = 4
+ 38FONT_HERSHEY_COMPLEX_SMALL = 5
+ 39FONT_HERSHEY_SCRIPT_SIMPLEX = 6
+ 40FONT_HERSHEY_SCRIPT_COMPLEX = 7
+ 41FONT_ITALIC = 16
+ 42
+ 43FILLED = -1
+ 44LINE_4 = 4
+ 45LINE_8 = 8
+ 46LINE_AA = 16
+ 47
+ 48_inline_mat = vf.Filter("_inline_mat")
+ 49_slice_mat = vf.Filter("_slice_mat")
+ 50_slice_write_mat = vf.Filter("_slice_write_mat")
+ 51
+ 52
+ 53_filter_scale = vf.Filter("Scale")
+ 54_filter_rectangle = vf.Filter("cv2.rectangle")
+ 55_filter_putText = vf.Filter("cv2.putText")
+ 56_filter_arrowedLine = vf.Filter("cv2.arrowedLine")
+ 57_filter_line = vf.Filter("cv2.line")
+ 58_filter_circle = vf.Filter("cv2.circle")
+ 59_filter_addWeighted = vf.Filter("cv2.addWeighted")
+ 60
+ 61
+ 62def _ts_to_fps(timestamps):
+ 63    return int(1 / (timestamps[1] - timestamps[0]))  # TODO: Fix for non-integer fps
+ 64
+ 65
+ 66def _fps_to_ts(fps, n_frames):
+ 67    assert type(fps) == int
+ 68    return [Fraction(i, fps) for i in range(n_frames)]
+ 69
+ 70
+ 71_global_cv2_server = None
+ 72
+ 73
+ 74def _server():
+ 75    global _global_cv2_server
+ 76    if _global_cv2_server is None:
+ 77        _global_cv2_server = vf.YrdenServer()
+ 78    return _global_cv2_server
+ 79
+ 80
+ 81def set_cv2_server(server: vf.YrdenServer):
+ 82    """Set the server to use for the cv2 frontend."""
+ 83    global _global_cv2_server
+ 84    assert isinstance(server, vf.YrdenServer)
+ 85    _global_cv2_server = server
+ 86
+ 87
+ 88class Frame:
+ 89    def __init__(self, f, fmt):
+ 90        self._f = f
+ 91        self._fmt = fmt
+ 92        self.shape = (fmt["height"], fmt["width"], 3)
+ 93
+ 94        # denotes that the frame has not yet been modified
+ 95        # when a frame is modified, it is converted to rgb24 first
+ 96        self._modified = False
+ 97
+ 98    def _mut(self):
+ 99        if self._modified:
+100            assert self._fmt["pix_fmt"] == "rgb24"
+101            return
+102
+103        self._modified = True
+104        if self._fmt["pix_fmt"] != "rgb24":
+105            self._f = _filter_scale(self._f, pix_fmt="rgb24")
+106            self._fmt["pix_fmt"] = "rgb24"
+107
+108    def numpy(self):
+109        """
+110        Return the frame as a numpy array.
+111        """
+112
+113        self._mut()
+114        spec = vf.Spec([Fraction(0, 1)], lambda t, i: self._f, self._fmt)
+115        loader = spec.load(_server())
+116
+117        frame_raster_rgb24 = loader[0]
+118        assert type(frame_raster_rgb24) == bytes
+119        assert len(frame_raster_rgb24) == self.shape[0] * self.shape[1] * 3
+120        raw_data_array = np.frombuffer(frame_raster_rgb24, dtype=np.uint8)
+121        frame = raw_data_array.reshape(self.shape)
+122        frame = frame[:, :, ::-1]  # convert RGB to BGR
+123        return frame
+124
+125    def __getitem__(self, key):
+126        if not isinstance(key, tuple):
+127            raise NotImplementedError("Only 2D slicing is supported")
+128
+129        if len(key) != 2:
+130            raise NotImplementedError("Only 2D slicing is supported")
+131
+132        if not all(isinstance(x, slice) for x in key):
+133            raise NotImplementedError("Only 2D slicing is supported")
+134
+135        miny = key[0].start if key[0].start is not None else 0
+136        maxy = key[0].stop if key[0].stop is not None else self.shape[0]
+137        minx = key[1].start if key[1].start is not None else 0
+138        maxx = key[1].stop if key[1].stop is not None else self.shape[1]
+139
+140        # handle negative indices
+141        if miny < 0:
+142            miny = self.shape[0] + miny
+143        if maxy < 0:
+144            maxy = self.shape[0] + maxy
+145        if minx < 0:
+146            minx = self.shape[1] + minx
+147        if maxx < 0:
+148            maxx = self.shape[1] + maxx
+149
+150        if (
+151            maxy <= miny
+152            or maxx <= minx
+153            or miny < 0
+154            or minx < 0
+155            or maxy > self.shape[0]
+156            or maxx > self.shape[1]
+157        ):
+158            raise NotImplementedError("Invalid slice")
+159
+160        f = _slice_mat(self._f, miny, maxy, minx, maxx)
+161        fmt = self._fmt.copy()
+162        fmt["width"] = maxx - minx
+163        fmt["height"] = maxy - miny
+164        return Frame(f, fmt)
+165
+166    def __setitem__(self, key, value):
+167        value = frameify(value, "value")
+168
+169        if not isinstance(key, tuple):
+170            raise NotImplementedError("Only 2D slicing is supported")
+171
+172        if len(key) != 2:
+173            raise NotImplementedError("Only 2D slicing is supported")
+174
+175        if not all(isinstance(x, slice) for x in key):
+176            raise NotImplementedError("Only 2D slicing is supported")
+177
+178        miny = key[0].start if key[0].start is not None else 0
+179        maxy = key[0].stop if key[0].stop is not None else self.shape[0]
+180        minx = key[1].start if key[1].start is not None else 0
+181        maxx = key[1].stop if key[1].stop is not None else self.shape[1]
+182
+183        # handle negative indices
+184        if miny < 0:
+185            miny = self.shape[0] + miny
+186        if maxy < 0:
+187            maxy = self.shape[0] + maxy
+188        if minx < 0:
+189            minx = self.shape[1] + minx
+190        if maxx < 0:
+191            maxx = self.shape[1] + maxx
+192
+193        if (
+194            maxy <= miny
+195            or maxx <= minx
+196            or miny < 0
+197            or minx < 0
+198            or maxy > self.shape[0]
+199            or maxx > self.shape[1]
+200        ):
+201            raise NotImplementedError("Invalid slice")
+202
+203        if value.shape[0] != maxy - miny or value.shape[1] != maxx - minx:
+204            raise NotImplementedError("Shape mismatch")
+205
+206        self._mut()
+207        value._mut()
+208
+209        self._f = _slice_write_mat(self._f, value._f, miny, maxy, minx, maxx)
+210
+211
+212def _inline_frame(arr):
+213    assert arr.dtype == np.uint8
+214    assert arr.ndim == 3
+215    assert arr.shape[2] == 3
+216
+217    # convert BGR to RGB
+218    arr = arr[:, :, ::-1]
+219
+220    width = arr.shape[1]
+221    height = arr.shape[0]
+222    pix_fmt = "rgb24"
+223
+224    f = _inline_mat(arr.tobytes(), width=width, height=height, pix_fmt=pix_fmt)
+225    fmt = {"width": width, "height": height, "pix_fmt": pix_fmt}
+226    return Frame(f, fmt)
+227
+228
+229class VideoCapture:
+230    def __init__(self, path):
+231        self._path = path
+232        server = _server()
+233        self._source = vf.Source(server, str(uuid.uuid4()), path, 0)
+234        self._next_frame_idx = 0
+235
+236    def isOpened(self):
+237        return True
+238
+239    def get(self, prop):
+240        if prop == CAP_PROP_FPS:
+241            return _ts_to_fps(self._source.ts())
+242        elif prop == CAP_PROP_FRAME_WIDTH:
+243            return self._source.fmt()["width"]
+244        elif prop == CAP_PROP_FRAME_HEIGHT:
+245            return self._source.fmt()["height"]
+246        elif prop == CAP_PROP_FRAME_COUNT:
+247            return len(self._source.ts())
+248        elif prop == CAP_PROP_POS_FRAMES:
+249            return self._next_frame_idx
+250
+251        raise Exception(f"Unknown property {prop}")
+252
+253    def set(self, prop, value):
+254        if prop == CAP_PROP_POS_FRAMES:
+255            assert value >= 0 and value < len(self._source.ts())
+256            self._next_frame_idx = value
+257        elif prop == CAP_PROP_POS_MSEC:
+258            t = Fraction(value, 1000)
+259            ts = self._source.ts()
+260            next_frame_idx = bisect_right(ts, t)
+261            self._next_frame_idx = next_frame_idx
+262        else:
+263            raise Exception(f"Unsupported property {prop}")
+264
+265    def read(self):
+266        if self._next_frame_idx >= len(self._source.ts()):
+267            return False, None
+268        frame = self._source.iloc[self._next_frame_idx]
+269        self._next_frame_idx += 1
+270        frame = Frame(frame, self._source.fmt())
+271        return True, frame
+272
+273    def release(self):
+274        pass
+275
+276
+277class VideoWriter:
+278    def __init__(self, path, fourcc, fps, size):
+279        assert isinstance(fourcc, VideoWriter_fourcc)
+280        if path is not None and not isinstance(path, str):
+281            raise Exception("path must be a string or None")
+282        self._path = path
+283        self._fourcc = fourcc
+284        self._fps = fps
+285        self._size = size
+286
+287        self._frames = []
+288        self._pix_fmt = "yuv420p"
+289
+290    def write(self, frame):
+291        frame = frameify(frame, "frame")
+292
+293        if frame._fmt["pix_fmt"] != self._pix_fmt:
+294            f_obj = _filter_scale(frame._f, pix_fmt=self._pix_fmt)
+295            self._frames.append(f_obj)
+296        else:
+297            self._frames.append(frame._f)
+298
+299    def release(self):
+300        if self._path is None:
+301            return
+302
+303        spec = self.spec()
+304        server = _server()
+305        spec.save(server, self._path)
+306
+307    def spec(self) -> vf.Spec:
+308        fmt = {
+309            "width": self._size[0],
+310            "height": self._size[1],
+311            "pix_fmt": self._pix_fmt,
+312        }
+313        domain = _fps_to_ts(self._fps, len(self._frames))
+314        spec = vf.Spec(domain, lambda t, i: self._frames[i], fmt)
+315        return spec
+316
+317
+318class VideoWriter_fourcc:
+319    def __init__(self, *args):
+320        self._args = args
+321
+322
+323def frameify(obj, field_name=None):
+324    """
+325    Turn an object (e.g., ndarray) into a Frame.
+326    """
+327
+328    if isinstance(obj, Frame):
+329        return obj
+330    elif isinstance(obj, np.ndarray):
+331        return _inline_frame(obj)
+332    else:
+333        if field_name is not None:
+334            raise Exception(
+335                f"Unsupported type for field {field_name}, expected Frame or np.ndarray"
+336            )
+337        else:
+338            raise Exception("Unsupported type, expected Frame or np.ndarray")
+339
+340
+341def imread(path, *args):
+342    if len(args) > 0:
+343        raise NotImplementedError("imread does not support additional arguments")
+344
+345    assert path.lower().endswith((".jpg", ".jpeg", ".png"))
+346    server = _server()
+347    source = vf.Source(server, str(uuid.uuid4()), path, 0)
+348    frame = Frame(source.iloc[0], source.fmt())
+349    return frame
+350
+351
+352def imwrite(path, img, *args):
+353    if len(args) > 0:
+354        raise NotImplementedError("imwrite does not support additional arguments")
+355
+356    img = frameify(img)
+357
+358    fmt = img._fmt.copy()
+359    width = fmt["width"]
+360    height = fmt["height"]
+361    f = img._f
+362
+363    domain = [Fraction(0, 1)]
+364
+365    if path.lower().endswith(".png"):
+366        img._mut()  # Make sure it's in rgb24
+367        spec = vf.Spec(
+368            domain,
+369            lambda t, i: img._f,
+370            {"width": width, "height": height, "pix_fmt": "rgb24"},
+371        )
+372        spec.save(_server(), path, encoder="png")
+373    elif path.lower().endswith((".jpg", ".jpeg")):
+374        if img._modified:
+375            # it's rgb24, we need to convert to something jpeg can handle
+376            f = _filter_scale(img._f, pix_fmt="yuv420p")
+377            fmt["pix_fmt"] = "yuv420p"
+378        else:
+379            if fmt["pix_fmt"] not in ["yuvj420p", "yuvj422p", "yuvj444p"]:
+380                f = _filter_scale(img._f, pix_fmt="yuvj420p")
+381                fmt["pix_fmt"] = "yuvj420p"
+382
+383        spec = vf.Spec(domain, lambda t, i: f, fmt)
+384        spec.save(_server(), path, encoder="mjpeg")
+385    else:
+386        raise Exception("Unsupported image format")
+387
+388
+389def vidplay(video, *args, **kwargs):
+390    """
+391    Play a vidformer video specification.
+392
+393    Args:
+394        video: one of [vidformer.Spec, vidformer.Source, vidformer.cv2.VideoWriter]
+395    """
+396
+397    if isinstance(video, vf.Spec):
+398        return video.play(_server(), *args, **kwargs)
+399    elif isinstance(video, vf.Source):
+400        return video.play(_server(), *args, **kwargs)
+401    elif isinstance(video, VideoWriter):
+402        return video.spec().play(_server(), *args, **kwargs)
+403    else:
+404        raise Exception("Unsupported video type to vidplay")
+405
+406
+407def rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):
+408    """
+409    cv.rectangle(	img, pt1, pt2, color[, thickness[, lineType[, shift]]]	)
+410    """
+411
+412    img = frameify(img)
+413    img._mut()
+414
+415    assert len(pt1) == 2
+416    assert len(pt2) == 2
+417    assert all(isinstance(x, int) for x in pt1)
+418    assert all(isinstance(x, int) for x in pt2)
+419
+420    assert len(color) == 3 or len(color) == 4
+421    color = [float(x) for x in color]
+422    if len(color) == 3:
+423        color.append(255.0)
+424
+425    args = []
+426    if thickness is not None:
+427        assert isinstance(thickness, int)
+428        args.append(thickness)
+429    if lineType is not None:
+430        assert isinstance(lineType, int)
+431        assert thickness is not None
+432        args.append(lineType)
+433    if shift is not None:
+434        assert isinstance(shift, int)
+435        assert shift is not None
+436        args.append(shift)
+437
+438    img._f = _filter_rectangle(img._f, pt1, pt2, color, *args)
+439
+440
+441def putText(
+442    img,
+443    text,
+444    org,
+445    fontFace,
+446    fontScale,
+447    color,
+448    thickness=None,
+449    lineType=None,
+450    bottomLeftOrigin=None,
+451):
+452    """
+453    cv.putText(	img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]	)
+454    """
+455
+456    img = frameify(img)
+457    img._mut()
+458
+459    assert isinstance(text, str)
+460
+461    assert len(org) == 2
+462    assert all(isinstance(x, int) for x in org)
+463
+464    assert isinstance(fontFace, int)
+465    assert isinstance(fontScale, float) or isinstance(fontScale, int)
+466    fontScale = float(fontScale)
+467
+468    assert len(color) == 3 or len(color) == 4
+469    color = [float(x) for x in color]
+470    if len(color) == 3:
+471        color.append(255.0)
+472
+473    args = []
+474    if thickness is not None:
+475        assert isinstance(thickness, int)
+476        args.append(thickness)
+477    if lineType is not None:
+478        assert isinstance(lineType, int)
+479        assert thickness is not None
+480        args.append(lineType)
+481    if bottomLeftOrigin is not None:
+482        assert isinstance(bottomLeftOrigin, bool)
+483        assert lineType is not None
+484        args.append(bottomLeftOrigin)
+485
+486    img._f = _filter_putText(img._f, text, org, fontFace, fontScale, color, *args)
+487
+488
+489def arrowedLine(
+490    img, pt1, pt2, color, thickness=None, line_type=None, shift=None, tipLength=None
+491):
+492    """
+493    cv.arrowedLine(	img, pt1, pt2, color[, thickness[, line_type[, shift[, tipLength]]]]	)
+494    """
+495    img = frameify(img)
+496    img._mut()
+497
+498    assert len(pt1) == 2
+499    assert len(pt2) == 2
+500    assert all(isinstance(x, int) for x in pt1)
+501    assert all(isinstance(x, int) for x in pt2)
+502
+503    assert len(color) == 3 or len(color) == 4
+504    color = [float(x) for x in color]
+505    if len(color) == 3:
+506        color.append(255.0)
+507
+508    args = []
+509    if thickness is not None:
+510        assert isinstance(thickness, int)
+511        args.append(thickness)
+512    if line_type is not None:
+513        assert isinstance(line_type, int)
+514        assert thickness is not None
+515        args.append(line_type)
+516    if shift is not None:
+517        assert isinstance(shift, int)
+518        assert shift is not None
+519        args.append(shift)
+520    if tipLength is not None:
+521        assert isinstance(tipLength, float)
+522        assert shift is not None
+523        args.append(tipLength)
+524
+525    img._f = _filter_arrowedLine(img._f, pt1, pt2, color, *args)
+526
+527
+528def line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):
+529    img = frameify(img)
+530    img._mut()
+531
+532    assert len(pt1) == 2
+533    assert len(pt2) == 2
+534    assert all(isinstance(x, int) for x in pt1)
+535    assert all(isinstance(x, int) for x in pt2)
+536
+537    assert len(color) == 3 or len(color) == 4
+538    color = [float(x) for x in color]
+539    if len(color) == 3:
+540        color.append(255.0)
+541
+542    args = []
+543    if thickness is not None:
+544        assert isinstance(thickness, int)
+545        args.append(thickness)
+546    if lineType is not None:
+547        assert isinstance(lineType, int)
+548        assert thickness is not None
+549        args.append(lineType)
+550    if shift is not None:
+551        assert isinstance(shift, int)
+552        assert shift is not None
+553        args.append(shift)
+554
+555    img._f = _filter_line(img._f, pt1, pt2, color, *args)
+556
+557
+558def circle(img, center, radius, color, thickness=None, lineType=None, shift=None):
+559    img = frameify(img)
+560    img._mut()
+561
+562    assert len(center) == 2
+563    assert all(isinstance(x, int) for x in center)
+564
+565    assert isinstance(radius, int)
+566
+567    assert len(color) == 3 or len(color) == 4
+568    color = [float(x) for x in color]
+569    if len(color) == 3:
+570        color.append(255.0)
+571
+572    args = []
+573    if thickness is not None:
+574        assert isinstance(thickness, int)
+575        args.append(thickness)
+576    if lineType is not None:
+577        assert isinstance(lineType, int)
+578        assert thickness is not None
+579        args.append(lineType)
+580    if shift is not None:
+581        assert isinstance(shift, int)
+582        assert shift is not None
+583        args.append(shift)
+584
+585    img._f = _filter_circle(img._f, center, radius, color, *args)
+586
+587
+588def getFontScaleFromHeight(*args, **kwargs):
+589    """
+590    cv.getFontScaleFromHeight(	fontFace, pixelHeight[, thickness]	)
+591    """
+592    if _opencv2 is None:
+593        raise NotImplementedError("getFontScaleFromHeight requires the cv2 module")
+594    return _opencv2.getFontScaleFromHeight(*args, **kwargs)
+595
+596
+597def getTextSize(*args, **kwargs):
+598    """
+599    cv.getTextSize(	text, fontFace, fontScale, thickness	)
+600    """
+601    if _opencv2 is None:
+602        raise NotImplementedError("getTextSize requires the cv2 module")
+603    return _opencv2.getTextSize(*args, **kwargs)
+604
+605
+606def addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=-1):
+607    """
+608    cv.addWeighted(	src1, alpha, src2, beta, gamma[, dst[, dtype]]	) -> 	dst
+609    """
+610    src1 = frameify(src1, "src1")
+611    src2 = frameify(src2, "src2")
+612    src1._mut()
+613    src2._mut()
+614
+615    if dst is None:
+616        dst = Frame(src1._f, src1._fmt.copy())
+617    else:
+618        assert isinstance(dst, Frame), "dst must be a Frame"
+619    dst._mut()
+620
+621    assert isinstance(alpha, float) or isinstance(alpha, int)
+622    assert isinstance(beta, float) or isinstance(beta, int)
+623    assert isinstance(gamma, float) or isinstance(gamma, int)
+624    alpha = float(alpha)
+625    beta = float(beta)
+626    gamma = float(gamma)
+627
+628    if dtype != -1:
+629        raise Exception("addWeighted does not support the dtype argument")
+630
+631    dst._f = _filter_addWeighted(src1._f, alpha, src2._f, beta, gamma)
+632    return dst
+633
+634
+635# Stubs for unimplemented functions
+636
+637
+638def clipLine(*args, **kwargs):
+639    raise NotImplementedError("clipLine is not yet implemented in the cv2 frontend")
+640
+641
+642def drawContours(*args, **kwargs):
+643    raise NotImplementedError("drawContours is not yet implemented in the cv2 frontend")
+644
+645
+646def drawMarker(*args, **kwargs):
+647    raise NotImplementedError("drawMarker is not yet implemented in the cv2 frontend")
+648
+649
+650def ellipse(*args, **kwargs):
+651    raise NotImplementedError("ellipse is not yet implemented in the cv2 frontend")
+652
+653
+654def ellipse2Poly(*args, **kwargs):
+655    raise NotImplementedError("ellipse2Poly is not yet implemented in the cv2 frontend")
+656
+657
+658def fillConvexPoly(*args, **kwargs):
+659    raise NotImplementedError(
+660        "fillConvexPoly is not yet implemented in the cv2 frontend"
+661    )
+662
+663
+664def fillPoly(*args, **kwargs):
+665    raise NotImplementedError("fillPoly is not yet implemented in the cv2 frontend")
+666
+667
+668def polylines(*args, **kwargs):
+669    raise NotImplementedError("polylines is not yet implemented in the cv2 frontend")
+
+ + +
+
+
+ CAP_PROP_POS_MSEC = +0 + + +
+ + + + +
+
+
+ CAP_PROP_POS_FRAMES = +1 + + +
+ + + + +
+
+
+ CAP_PROP_FRAME_WIDTH = +3 + + +
+ + + + +
+
+
+ CAP_PROP_FRAME_HEIGHT = +4 + + +
+ + + + +
+
+
+ CAP_PROP_FPS = +5 + + +
+ + + + +
+
+
+ CAP_PROP_FRAME_COUNT = +7 + + +
+ + + + +
+
+
+ FONT_HERSHEY_SIMPLEX = +0 + + +
+ + + + +
+
+
+ FONT_HERSHEY_PLAIN = +1 + + +
+ + + + +
+
+
+ FONT_HERSHEY_DUPLEX = +2 + + +
+ + + + +
+
+
+ FONT_HERSHEY_COMPLEX = +3 + + +
+ + + + +
+
+
+ FONT_HERSHEY_TRIPLEX = +4 + + +
+ + + + +
+
+
+ FONT_HERSHEY_COMPLEX_SMALL = +5 + + +
+ + + + +
+
+
+ FONT_HERSHEY_SCRIPT_SIMPLEX = +6 + + +
+ + + + +
+
+
+ FONT_HERSHEY_SCRIPT_COMPLEX = +7 + + +
+ + + + +
+
+
+ FONT_ITALIC = +16 + + +
+ + + + +
+
+
+ FILLED = +-1 + + +
+ + + + +
+
+
+ LINE_4 = +4 + + +
+ + + + +
+
+
+ LINE_8 = +8 + + +
+ + + + +
+
+
+ LINE_AA = +16 + + +
+ + + + +
+
+ +
+ + def + set_cv2_server(server: vidformer.vf.YrdenServer): + + + +
+ +
82def set_cv2_server(server: vf.YrdenServer):
+83    """Set the server to use for the cv2 frontend."""
+84    global _global_cv2_server
+85    assert isinstance(server, vf.YrdenServer)
+86    _global_cv2_server = server
+
+ + +

Set the server to use for the cv2 frontend.

+
+ + +
+
+ +
+ + class + Frame: + + + +
+ +
 89class Frame:
+ 90    def __init__(self, f, fmt):
+ 91        self._f = f
+ 92        self._fmt = fmt
+ 93        self.shape = (fmt["height"], fmt["width"], 3)
+ 94
+ 95        # denotes that the frame has not yet been modified
+ 96        # when a frame is modified, it is converted to rgb24 first
+ 97        self._modified = False
+ 98
+ 99    def _mut(self):
+100        if self._modified:
+101            assert self._fmt["pix_fmt"] == "rgb24"
+102            return
+103
+104        self._modified = True
+105        if self._fmt["pix_fmt"] != "rgb24":
+106            self._f = _filter_scale(self._f, pix_fmt="rgb24")
+107            self._fmt["pix_fmt"] = "rgb24"
+108
+109    def numpy(self):
+110        """
+111        Return the frame as a numpy array.
+112        """
+113
+114        self._mut()
+115        spec = vf.Spec([Fraction(0, 1)], lambda t, i: self._f, self._fmt)
+116        loader = spec.load(_server())
+117
+118        frame_raster_rgb24 = loader[0]
+119        assert type(frame_raster_rgb24) == bytes
+120        assert len(frame_raster_rgb24) == self.shape[0] * self.shape[1] * 3
+121        raw_data_array = np.frombuffer(frame_raster_rgb24, dtype=np.uint8)
+122        frame = raw_data_array.reshape(self.shape)
+123        frame = frame[:, :, ::-1]  # convert RGB to BGR
+124        return frame
+125
+126    def __getitem__(self, key):
+127        if not isinstance(key, tuple):
+128            raise NotImplementedError("Only 2D slicing is supported")
+129
+130        if len(key) != 2:
+131            raise NotImplementedError("Only 2D slicing is supported")
+132
+133        if not all(isinstance(x, slice) for x in key):
+134            raise NotImplementedError("Only 2D slicing is supported")
+135
+136        miny = key[0].start if key[0].start is not None else 0
+137        maxy = key[0].stop if key[0].stop is not None else self.shape[0]
+138        minx = key[1].start if key[1].start is not None else 0
+139        maxx = key[1].stop if key[1].stop is not None else self.shape[1]
+140
+141        # handle negative indices
+142        if miny < 0:
+143            miny = self.shape[0] + miny
+144        if maxy < 0:
+145            maxy = self.shape[0] + maxy
+146        if minx < 0:
+147            minx = self.shape[1] + minx
+148        if maxx < 0:
+149            maxx = self.shape[1] + maxx
+150
+151        if (
+152            maxy <= miny
+153            or maxx <= minx
+154            or miny < 0
+155            or minx < 0
+156            or maxy > self.shape[0]
+157            or maxx > self.shape[1]
+158        ):
+159            raise NotImplementedError("Invalid slice")
+160
+161        f = _slice_mat(self._f, miny, maxy, minx, maxx)
+162        fmt = self._fmt.copy()
+163        fmt["width"] = maxx - minx
+164        fmt["height"] = maxy - miny
+165        return Frame(f, fmt)
+166
+167    def __setitem__(self, key, value):
+168        value = frameify(value, "value")
+169
+170        if not isinstance(key, tuple):
+171            raise NotImplementedError("Only 2D slicing is supported")
+172
+173        if len(key) != 2:
+174            raise NotImplementedError("Only 2D slicing is supported")
+175
+176        if not all(isinstance(x, slice) for x in key):
+177            raise NotImplementedError("Only 2D slicing is supported")
+178
+179        miny = key[0].start if key[0].start is not None else 0
+180        maxy = key[0].stop if key[0].stop is not None else self.shape[0]
+181        minx = key[1].start if key[1].start is not None else 0
+182        maxx = key[1].stop if key[1].stop is not None else self.shape[1]
+183
+184        # handle negative indices
+185        if miny < 0:
+186            miny = self.shape[0] + miny
+187        if maxy < 0:
+188            maxy = self.shape[0] + maxy
+189        if minx < 0:
+190            minx = self.shape[1] + minx
+191        if maxx < 0:
+192            maxx = self.shape[1] + maxx
+193
+194        if (
+195            maxy <= miny
+196            or maxx <= minx
+197            or miny < 0
+198            or minx < 0
+199            or maxy > self.shape[0]
+200            or maxx > self.shape[1]
+201        ):
+202            raise NotImplementedError("Invalid slice")
+203
+204        if value.shape[0] != maxy - miny or value.shape[1] != maxx - minx:
+205            raise NotImplementedError("Shape mismatch")
+206
+207        self._mut()
+208        value._mut()
+209
+210        self._f = _slice_write_mat(self._f, value._f, miny, maxy, minx, maxx)
+
+ + + + +
+ +
+ + Frame(f, fmt) + + + +
+ +
90    def __init__(self, f, fmt):
+91        self._f = f
+92        self._fmt = fmt
+93        self.shape = (fmt["height"], fmt["width"], 3)
+94
+95        # denotes that the frame has not yet been modified
+96        # when a frame is modified, it is converted to rgb24 first
+97        self._modified = False
+
+ + + + +
+
+
+ shape + + +
+ + + + +
+
+ +
+ + def + numpy(self): + + + +
+ +
109    def numpy(self):
+110        """
+111        Return the frame as a numpy array.
+112        """
+113
+114        self._mut()
+115        spec = vf.Spec([Fraction(0, 1)], lambda t, i: self._f, self._fmt)
+116        loader = spec.load(_server())
+117
+118        frame_raster_rgb24 = loader[0]
+119        assert type(frame_raster_rgb24) == bytes
+120        assert len(frame_raster_rgb24) == self.shape[0] * self.shape[1] * 3
+121        raw_data_array = np.frombuffer(frame_raster_rgb24, dtype=np.uint8)
+122        frame = raw_data_array.reshape(self.shape)
+123        frame = frame[:, :, ::-1]  # convert RGB to BGR
+124        return frame
+
+ + +

Return the frame as a numpy array.

+
+ + +
+
+
+ +
+ + class + VideoCapture: + + + +
+ +
230class VideoCapture:
+231    def __init__(self, path):
+232        self._path = path
+233        server = _server()
+234        self._source = vf.Source(server, str(uuid.uuid4()), path, 0)
+235        self._next_frame_idx = 0
+236
+237    def isOpened(self):
+238        return True
+239
+240    def get(self, prop):
+241        if prop == CAP_PROP_FPS:
+242            return _ts_to_fps(self._source.ts())
+243        elif prop == CAP_PROP_FRAME_WIDTH:
+244            return self._source.fmt()["width"]
+245        elif prop == CAP_PROP_FRAME_HEIGHT:
+246            return self._source.fmt()["height"]
+247        elif prop == CAP_PROP_FRAME_COUNT:
+248            return len(self._source.ts())
+249        elif prop == CAP_PROP_POS_FRAMES:
+250            return self._next_frame_idx
+251
+252        raise Exception(f"Unknown property {prop}")
+253
+254    def set(self, prop, value):
+255        if prop == CAP_PROP_POS_FRAMES:
+256            assert value >= 0 and value < len(self._source.ts())
+257            self._next_frame_idx = value
+258        elif prop == CAP_PROP_POS_MSEC:
+259            t = Fraction(value, 1000)
+260            ts = self._source.ts()
+261            next_frame_idx = bisect_right(ts, t)
+262            self._next_frame_idx = next_frame_idx
+263        else:
+264            raise Exception(f"Unsupported property {prop}")
+265
+266    def read(self):
+267        if self._next_frame_idx >= len(self._source.ts()):
+268            return False, None
+269        frame = self._source.iloc[self._next_frame_idx]
+270        self._next_frame_idx += 1
+271        frame = Frame(frame, self._source.fmt())
+272        return True, frame
+273
+274    def release(self):
+275        pass
+
+ + + + +
+ +
+ + VideoCapture(path) + + + +
+ +
231    def __init__(self, path):
+232        self._path = path
+233        server = _server()
+234        self._source = vf.Source(server, str(uuid.uuid4()), path, 0)
+235        self._next_frame_idx = 0
+
+ + + + +
+
+ +
+ + def + isOpened(self): + + + +
+ +
237    def isOpened(self):
+238        return True
+
+ + + + +
+
+ +
+ + def + get(self, prop): + + + +
+ +
240    def get(self, prop):
+241        if prop == CAP_PROP_FPS:
+242            return _ts_to_fps(self._source.ts())
+243        elif prop == CAP_PROP_FRAME_WIDTH:
+244            return self._source.fmt()["width"]
+245        elif prop == CAP_PROP_FRAME_HEIGHT:
+246            return self._source.fmt()["height"]
+247        elif prop == CAP_PROP_FRAME_COUNT:
+248            return len(self._source.ts())
+249        elif prop == CAP_PROP_POS_FRAMES:
+250            return self._next_frame_idx
+251
+252        raise Exception(f"Unknown property {prop}")
+
+ + + + +
+
+ +
+ + def + set(self, prop, value): + + + +
+ +
254    def set(self, prop, value):
+255        if prop == CAP_PROP_POS_FRAMES:
+256            assert value >= 0 and value < len(self._source.ts())
+257            self._next_frame_idx = value
+258        elif prop == CAP_PROP_POS_MSEC:
+259            t = Fraction(value, 1000)
+260            ts = self._source.ts()
+261            next_frame_idx = bisect_right(ts, t)
+262            self._next_frame_idx = next_frame_idx
+263        else:
+264            raise Exception(f"Unsupported property {prop}")
+
+ + + + +
+
+ +
+ + def + read(self): + + + +
+ +
266    def read(self):
+267        if self._next_frame_idx >= len(self._source.ts()):
+268            return False, None
+269        frame = self._source.iloc[self._next_frame_idx]
+270        self._next_frame_idx += 1
+271        frame = Frame(frame, self._source.fmt())
+272        return True, frame
+
+ + + + +
+
+ +
+ + def + release(self): + + + +
+ +
274    def release(self):
+275        pass
+
+ + + + +
+
+
+ +
+ + class + VideoWriter: + + + +
+ +
278class VideoWriter:
+279    def __init__(self, path, fourcc, fps, size):
+280        assert isinstance(fourcc, VideoWriter_fourcc)
+281        if path is not None and not isinstance(path, str):
+282            raise Exception("path must be a string or None")
+283        self._path = path
+284        self._fourcc = fourcc
+285        self._fps = fps
+286        self._size = size
+287
+288        self._frames = []
+289        self._pix_fmt = "yuv420p"
+290
+291    def write(self, frame):
+292        frame = frameify(frame, "frame")
+293
+294        if frame._fmt["pix_fmt"] != self._pix_fmt:
+295            f_obj = _filter_scale(frame._f, pix_fmt=self._pix_fmt)
+296            self._frames.append(f_obj)
+297        else:
+298            self._frames.append(frame._f)
+299
+300    def release(self):
+301        if self._path is None:
+302            return
+303
+304        spec = self.spec()
+305        server = _server()
+306        spec.save(server, self._path)
+307
+308    def spec(self) -> vf.Spec:
+309        fmt = {
+310            "width": self._size[0],
+311            "height": self._size[1],
+312            "pix_fmt": self._pix_fmt,
+313        }
+314        domain = _fps_to_ts(self._fps, len(self._frames))
+315        spec = vf.Spec(domain, lambda t, i: self._frames[i], fmt)
+316        return spec
+
+ + + + +
+ +
+ + VideoWriter(path, fourcc, fps, size) + + + +
+ +
279    def __init__(self, path, fourcc, fps, size):
+280        assert isinstance(fourcc, VideoWriter_fourcc)
+281        if path is not None and not isinstance(path, str):
+282            raise Exception("path must be a string or None")
+283        self._path = path
+284        self._fourcc = fourcc
+285        self._fps = fps
+286        self._size = size
+287
+288        self._frames = []
+289        self._pix_fmt = "yuv420p"
+
+ + + + +
+
+ +
+ + def + write(self, frame): + + + +
+ +
291    def write(self, frame):
+292        frame = frameify(frame, "frame")
+293
+294        if frame._fmt["pix_fmt"] != self._pix_fmt:
+295            f_obj = _filter_scale(frame._f, pix_fmt=self._pix_fmt)
+296            self._frames.append(f_obj)
+297        else:
+298            self._frames.append(frame._f)
+
+ + + + +
+
+ +
+ + def + release(self): + + + +
+ +
300    def release(self):
+301        if self._path is None:
+302            return
+303
+304        spec = self.spec()
+305        server = _server()
+306        spec.save(server, self._path)
+
+ + + + +
+
+ +
+ + def + spec(self) -> vidformer.vf.Spec: + + + +
+ +
308    def spec(self) -> vf.Spec:
+309        fmt = {
+310            "width": self._size[0],
+311            "height": self._size[1],
+312            "pix_fmt": self._pix_fmt,
+313        }
+314        domain = _fps_to_ts(self._fps, len(self._frames))
+315        spec = vf.Spec(domain, lambda t, i: self._frames[i], fmt)
+316        return spec
+
+ + + + +
+
+
+ +
+ + class + VideoWriter_fourcc: + + + +
+ +
319class VideoWriter_fourcc:
+320    def __init__(self, *args):
+321        self._args = args
+
+ + + + +
+ +
+ + VideoWriter_fourcc(*args) + + + +
+ +
320    def __init__(self, *args):
+321        self._args = args
+
+ + + + +
+
+
+ +
+ + def + frameify(obj, field_name=None): + + + +
+ +
324def frameify(obj, field_name=None):
+325    """
+326    Turn an object (e.g., ndarray) into a Frame.
+327    """
+328
+329    if isinstance(obj, Frame):
+330        return obj
+331    elif isinstance(obj, np.ndarray):
+332        return _inline_frame(obj)
+333    else:
+334        if field_name is not None:
+335            raise Exception(
+336                f"Unsupported type for field {field_name}, expected Frame or np.ndarray"
+337            )
+338        else:
+339            raise Exception("Unsupported type, expected Frame or np.ndarray")
+
+ + +

Turn an object (e.g., ndarray) into a Frame.

+
+ + +
+
+ +
+ + def + imread(path, *args): + + + +
+ +
342def imread(path, *args):
+343    if len(args) > 0:
+344        raise NotImplementedError("imread does not support additional arguments")
+345
+346    assert path.lower().endswith((".jpg", ".jpeg", ".png"))
+347    server = _server()
+348    source = vf.Source(server, str(uuid.uuid4()), path, 0)
+349    frame = Frame(source.iloc[0], source.fmt())
+350    return frame
+
+ + + + +
+
+ +
+ + def + imwrite(path, img, *args): + + + +
+ +
353def imwrite(path, img, *args):
+354    if len(args) > 0:
+355        raise NotImplementedError("imwrite does not support additional arguments")
+356
+357    img = frameify(img)
+358
+359    fmt = img._fmt.copy()
+360    width = fmt["width"]
+361    height = fmt["height"]
+362    f = img._f
+363
+364    domain = [Fraction(0, 1)]
+365
+366    if path.lower().endswith(".png"):
+367        img._mut()  # Make sure it's in rgb24
+368        spec = vf.Spec(
+369            domain,
+370            lambda t, i: img._f,
+371            {"width": width, "height": height, "pix_fmt": "rgb24"},
+372        )
+373        spec.save(_server(), path, encoder="png")
+374    elif path.lower().endswith((".jpg", ".jpeg")):
+375        if img._modified:
+376            # it's rgb24, we need to convert to something jpeg can handle
+377            f = _filter_scale(img._f, pix_fmt="yuv420p")
+378            fmt["pix_fmt"] = "yuv420p"
+379        else:
+380            if fmt["pix_fmt"] not in ["yuvj420p", "yuvj422p", "yuvj444p"]:
+381                f = _filter_scale(img._f, pix_fmt="yuvj420p")
+382                fmt["pix_fmt"] = "yuvj420p"
+383
+384        spec = vf.Spec(domain, lambda t, i: f, fmt)
+385        spec.save(_server(), path, encoder="mjpeg")
+386    else:
+387        raise Exception("Unsupported image format")
+
+ + + + +
+
+ +
+ + def + vidplay(video, *args, **kwargs): + + + +
+ +
390def vidplay(video, *args, **kwargs):
+391    """
+392    Play a vidformer video specification.
+393
+394    Args:
+395        video: one of [vidformer.Spec, vidformer.Source, vidformer.cv2.VideoWriter]
+396    """
+397
+398    if isinstance(video, vf.Spec):
+399        return video.play(_server(), *args, **kwargs)
+400    elif isinstance(video, vf.Source):
+401        return video.play(_server(), *args, **kwargs)
+402    elif isinstance(video, VideoWriter):
+403        return video.spec().play(_server(), *args, **kwargs)
+404    else:
+405        raise Exception("Unsupported video type to vidplay")
+
+ + +

Play a vidformer video specification.

+ +

Args: + video: one of [vidformer.Spec, vidformer.Source, vidformer.cv2.VideoWriter]

+
+ + +
+
+ +
+ + def + rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None): + + + +
+ +
408def rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):
+409    """
+410    cv.rectangle(	img, pt1, pt2, color[, thickness[, lineType[, shift]]]	)
+411    """
+412
+413    img = frameify(img)
+414    img._mut()
+415
+416    assert len(pt1) == 2
+417    assert len(pt2) == 2
+418    assert all(isinstance(x, int) for x in pt1)
+419    assert all(isinstance(x, int) for x in pt2)
+420
+421    assert len(color) == 3 or len(color) == 4
+422    color = [float(x) for x in color]
+423    if len(color) == 3:
+424        color.append(255.0)
+425
+426    args = []
+427    if thickness is not None:
+428        assert isinstance(thickness, int)
+429        args.append(thickness)
+430    if lineType is not None:
+431        assert isinstance(lineType, int)
+432        assert thickness is not None
+433        args.append(lineType)
+434    if shift is not None:
+435        assert isinstance(shift, int)
+436        assert shift is not None
+437        args.append(shift)
+438
+439    img._f = _filter_rectangle(img._f, pt1, pt2, color, *args)
+
+ + +

cv.rectangle( img, pt1, pt2, color[, thickness[, lineType[, shift]]] )

+
+ + +
+
+ +
+ + def + putText( img, text, org, fontFace, fontScale, color, thickness=None, lineType=None, bottomLeftOrigin=None): + + + +
+ +
442def putText(
+443    img,
+444    text,
+445    org,
+446    fontFace,
+447    fontScale,
+448    color,
+449    thickness=None,
+450    lineType=None,
+451    bottomLeftOrigin=None,
+452):
+453    """
+454    cv.putText(	img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]	)
+455    """
+456
+457    img = frameify(img)
+458    img._mut()
+459
+460    assert isinstance(text, str)
+461
+462    assert len(org) == 2
+463    assert all(isinstance(x, int) for x in org)
+464
+465    assert isinstance(fontFace, int)
+466    assert isinstance(fontScale, float) or isinstance(fontScale, int)
+467    fontScale = float(fontScale)
+468
+469    assert len(color) == 3 or len(color) == 4
+470    color = [float(x) for x in color]
+471    if len(color) == 3:
+472        color.append(255.0)
+473
+474    args = []
+475    if thickness is not None:
+476        assert isinstance(thickness, int)
+477        args.append(thickness)
+478    if lineType is not None:
+479        assert isinstance(lineType, int)
+480        assert thickness is not None
+481        args.append(lineType)
+482    if bottomLeftOrigin is not None:
+483        assert isinstance(bottomLeftOrigin, bool)
+484        assert lineType is not None
+485        args.append(bottomLeftOrigin)
+486
+487    img._f = _filter_putText(img._f, text, org, fontFace, fontScale, color, *args)
+
+ + +

cv.putText( img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]] )

+
+ + +
+
+ +
+ + def + arrowedLine( img, pt1, pt2, color, thickness=None, line_type=None, shift=None, tipLength=None): + + + +
+ +
490def arrowedLine(
+491    img, pt1, pt2, color, thickness=None, line_type=None, shift=None, tipLength=None
+492):
+493    """
+494    cv.arrowedLine(	img, pt1, pt2, color[, thickness[, line_type[, shift[, tipLength]]]]	)
+495    """
+496    img = frameify(img)
+497    img._mut()
+498
+499    assert len(pt1) == 2
+500    assert len(pt2) == 2
+501    assert all(isinstance(x, int) for x in pt1)
+502    assert all(isinstance(x, int) for x in pt2)
+503
+504    assert len(color) == 3 or len(color) == 4
+505    color = [float(x) for x in color]
+506    if len(color) == 3:
+507        color.append(255.0)
+508
+509    args = []
+510    if thickness is not None:
+511        assert isinstance(thickness, int)
+512        args.append(thickness)
+513    if line_type is not None:
+514        assert isinstance(line_type, int)
+515        assert thickness is not None
+516        args.append(line_type)
+517    if shift is not None:
+518        assert isinstance(shift, int)
+519        assert shift is not None
+520        args.append(shift)
+521    if tipLength is not None:
+522        assert isinstance(tipLength, float)
+523        assert shift is not None
+524        args.append(tipLength)
+525
+526    img._f = _filter_arrowedLine(img._f, pt1, pt2, color, *args)
+
+ + +

cv.arrowedLine( img, pt1, pt2, color[, thickness[, line_type[, shift[, tipLength]]]] )

+
+ + +
+
+ +
+ + def + line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None): + + + +
+ +
529def line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):
+530    img = frameify(img)
+531    img._mut()
+532
+533    assert len(pt1) == 2
+534    assert len(pt2) == 2
+535    assert all(isinstance(x, int) for x in pt1)
+536    assert all(isinstance(x, int) for x in pt2)
+537
+538    assert len(color) == 3 or len(color) == 4
+539    color = [float(x) for x in color]
+540    if len(color) == 3:
+541        color.append(255.0)
+542
+543    args = []
+544    if thickness is not None:
+545        assert isinstance(thickness, int)
+546        args.append(thickness)
+547    if lineType is not None:
+548        assert isinstance(lineType, int)
+549        assert thickness is not None
+550        args.append(lineType)
+551    if shift is not None:
+552        assert isinstance(shift, int)
+553        assert shift is not None
+554        args.append(shift)
+555
+556    img._f = _filter_line(img._f, pt1, pt2, color, *args)
+
+ + + + +
+
+ +
+ + def + circle( img, center, radius, color, thickness=None, lineType=None, shift=None): + + + +
+ +
559def circle(img, center, radius, color, thickness=None, lineType=None, shift=None):
+560    img = frameify(img)
+561    img._mut()
+562
+563    assert len(center) == 2
+564    assert all(isinstance(x, int) for x in center)
+565
+566    assert isinstance(radius, int)
+567
+568    assert len(color) == 3 or len(color) == 4
+569    color = [float(x) for x in color]
+570    if len(color) == 3:
+571        color.append(255.0)
+572
+573    args = []
+574    if thickness is not None:
+575        assert isinstance(thickness, int)
+576        args.append(thickness)
+577    if lineType is not None:
+578        assert isinstance(lineType, int)
+579        assert thickness is not None
+580        args.append(lineType)
+581    if shift is not None:
+582        assert isinstance(shift, int)
+583        assert shift is not None
+584        args.append(shift)
+585
+586    img._f = _filter_circle(img._f, center, radius, color, *args)
+
+ + + + +
+
+ +
+ + def + getFontScaleFromHeight(*args, **kwargs): + + + +
+ +
589def getFontScaleFromHeight(*args, **kwargs):
+590    """
+591    cv.getFontScaleFromHeight(	fontFace, pixelHeight[, thickness]	)
+592    """
+593    if _opencv2 is None:
+594        raise NotImplementedError("getFontScaleFromHeight requires the cv2 module")
+595    return _opencv2.getFontScaleFromHeight(*args, **kwargs)
+
+ + +

cv.getFontScaleFromHeight( fontFace, pixelHeight[, thickness] )

+
+ + +
+
+ +
+ + def + getTextSize(*args, **kwargs): + + + +
+ +
598def getTextSize(*args, **kwargs):
+599    """
+600    cv.getTextSize(	text, fontFace, fontScale, thickness	)
+601    """
+602    if _opencv2 is None:
+603        raise NotImplementedError("getTextSize requires the cv2 module")
+604    return _opencv2.getTextSize(*args, **kwargs)
+
+ + +

cv.getTextSize( text, fontFace, fontScale, thickness )

+
+ + +
+
+ +
+ + def + addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=-1): + + + +
+ +
607def addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=-1):
+608    """
+609    cv.addWeighted(	src1, alpha, src2, beta, gamma[, dst[, dtype]]	) -> 	dst
+610    """
+611    src1 = frameify(src1, "src1")
+612    src2 = frameify(src2, "src2")
+613    src1._mut()
+614    src2._mut()
+615
+616    if dst is None:
+617        dst = Frame(src1._f, src1._fmt.copy())
+618    else:
+619        assert isinstance(dst, Frame), "dst must be a Frame"
+620    dst._mut()
+621
+622    assert isinstance(alpha, float) or isinstance(alpha, int)
+623    assert isinstance(beta, float) or isinstance(beta, int)
+624    assert isinstance(gamma, float) or isinstance(gamma, int)
+625    alpha = float(alpha)
+626    beta = float(beta)
+627    gamma = float(gamma)
+628
+629    if dtype != -1:
+630        raise Exception("addWeighted does not support the dtype argument")
+631
+632    dst._f = _filter_addWeighted(src1._f, alpha, src2._f, beta, gamma)
+633    return dst
+
+ + +

cv.addWeighted( src1, alpha, src2, beta, gamma[, dst[, dtype]] ) -> dst

+
+ + +
+
+ +
+ + def + clipLine(*args, **kwargs): + + + +
+ +
639def clipLine(*args, **kwargs):
+640    raise NotImplementedError("clipLine is not yet implemented in the cv2 frontend")
+
+ + + + +
+
+ +
+ + def + drawContours(*args, **kwargs): + + + +
+ +
643def drawContours(*args, **kwargs):
+644    raise NotImplementedError("drawContours is not yet implemented in the cv2 frontend")
+
+ + + + +
+
+ +
+ + def + drawMarker(*args, **kwargs): + + + +
+ +
647def drawMarker(*args, **kwargs):
+648    raise NotImplementedError("drawMarker is not yet implemented in the cv2 frontend")
+
+ + + + +
+
+ +
+ + def + ellipse(*args, **kwargs): + + + +
+ +
651def ellipse(*args, **kwargs):
+652    raise NotImplementedError("ellipse is not yet implemented in the cv2 frontend")
+
+ + + + +
+
+ +
+ + def + ellipse2Poly(*args, **kwargs): + + + +
+ +
655def ellipse2Poly(*args, **kwargs):
+656    raise NotImplementedError("ellipse2Poly is not yet implemented in the cv2 frontend")
+
+ + + + +
+
+ +
+ + def + fillConvexPoly(*args, **kwargs): + + + +
+ +
659def fillConvexPoly(*args, **kwargs):
+660    raise NotImplementedError(
+661        "fillConvexPoly is not yet implemented in the cv2 frontend"
+662    )
+
+ + + + +
+
+ +
+ + def + fillPoly(*args, **kwargs): + + + +
+ +
665def fillPoly(*args, **kwargs):
+666    raise NotImplementedError("fillPoly is not yet implemented in the cv2 frontend")
+
+ + + + +
+
+ +
+ + def + polylines(*args, **kwargs): + + + +
+ +
669def polylines(*args, **kwargs):
+670    raise NotImplementedError("polylines is not yet implemented in the cv2 frontend")
+
+ + + + +
+
+ + \ No newline at end of file diff --git a/vidformer-py.html b/vidformer-py.html new file mode 100644 index 0000000..ac07dac --- /dev/null +++ b/vidformer-py.html @@ -0,0 +1,225 @@ + + + + + + vidformer-py - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

vidformer-py

+

PyPI version +License

+

vidformer-py is a Python 🐍 interface for vidformer. +Our getting started guide explains how to use it.

+

Quick links:

+ +

Publish:

+
 export FLIT_USERNAME='__token__' FLIT_PASSWORD='<token>'
+flit publish
+
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + diff --git a/vidformer-py/index.html b/vidformer-py/index.html new file mode 100644 index 0000000..a8462de --- /dev/null +++ b/vidformer-py/index.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/vidformer-py/search.js b/vidformer-py/search.js new file mode 100644 index 0000000..d850197 --- /dev/null +++ b/vidformer-py/search.js @@ -0,0 +1,46 @@ +window.pdocSearch = (function(){ +/** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();ovidformer-py is a Python \ud83d\udc0d interface for vidformer.

\n\n

Quick links:

\n\n\n"}, "vidformer.vf.Spec": {"fullname": "vidformer.vf.Spec", "modulename": "vidformer.vf", "qualname": "Spec", "kind": "class", "doc": "

A video transformation specification.

\n\n

See https://ixlab.github.io/vidformer/concepts.html for more information.

\n"}, "vidformer.vf.Spec.__init__": {"fullname": "vidformer.vf.Spec.__init__", "modulename": "vidformer.vf", "qualname": "Spec.__init__", "kind": "function", "doc": "

\n", "signature": "(domain: list[fractions.Fraction], render, fmt: dict)"}, "vidformer.vf.Spec.play": {"fullname": "vidformer.vf.Spec.play", "modulename": "vidformer.vf", "qualname": "Spec.play", "kind": "function", "doc": "

Play the video live in the notebook.

\n", "signature": "(self, server, method='html', verbose=False):", "funcdef": "def"}, "vidformer.vf.Spec.load": {"fullname": "vidformer.vf.Spec.load", "modulename": "vidformer.vf", "qualname": "Spec.load", "kind": "function", "doc": "

\n", "signature": "(self, server):", "funcdef": "def"}, "vidformer.vf.Spec.save": {"fullname": "vidformer.vf.Spec.save", "modulename": "vidformer.vf", "qualname": "Spec.save", "kind": "function", "doc": "

Save the video to a file.

\n", "signature": "(self, server, pth, encoder=None, encoder_opts=None, format=None):", "funcdef": "def"}, "vidformer.vf.Loader": {"fullname": "vidformer.vf.Loader", "modulename": "vidformer.vf", "qualname": "Loader", "kind": "class", "doc": "

\n"}, "vidformer.vf.Loader.__init__": {"fullname": "vidformer.vf.Loader.__init__", "modulename": "vidformer.vf", "qualname": "Loader.__init__", "kind": "function", "doc": "

\n", "signature": "(server, namespace: str, domain)"}, "vidformer.vf.YrdenServer": {"fullname": "vidformer.vf.YrdenServer", "modulename": "vidformer.vf", "qualname": "YrdenServer", "kind": "class", "doc": "

A connection to a Yrden server.

\n\n

A yrden server is the main API for local use of vidformer.

\n"}, "vidformer.vf.YrdenServer.__init__": {"fullname": "vidformer.vf.YrdenServer.__init__", "modulename": "vidformer.vf", "qualname": "YrdenServer.__init__", "kind": "function", "doc": "

Connect to a Yrden server

\n\n

Can either connect to an existing server, if domain and port are provided, or start a new server using the provided binary.\nIf no domain or binary is provided, the VIDFORMER_BIN environment variable is used.

\n", "signature": "(domain=None, port=None, bin=None, hls_prefix=None)"}, "vidformer.vf.YrdenServer.hls_js_url": {"fullname": "vidformer.vf.YrdenServer.hls_js_url", "modulename": "vidformer.vf", "qualname": "YrdenServer.hls_js_url", "kind": "function", "doc": "

Return the link to the yrden-hosted hls.js file

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.vf.SourceExpr": {"fullname": "vidformer.vf.SourceExpr", "modulename": "vidformer.vf", "qualname": "SourceExpr", "kind": "class", "doc": "

\n"}, "vidformer.vf.SourceExpr.__init__": {"fullname": "vidformer.vf.SourceExpr.__init__", "modulename": "vidformer.vf", "qualname": "SourceExpr.__init__", "kind": "function", "doc": "

\n", "signature": "(source, idx, is_iloc)"}, "vidformer.vf.SourceILoc": {"fullname": "vidformer.vf.SourceILoc", "modulename": "vidformer.vf", "qualname": "SourceILoc", "kind": "class", "doc": "

\n"}, "vidformer.vf.SourceILoc.__init__": {"fullname": "vidformer.vf.SourceILoc.__init__", "modulename": "vidformer.vf", "qualname": "SourceILoc.__init__", "kind": "function", "doc": "

\n", "signature": "(source)"}, "vidformer.vf.Source": {"fullname": "vidformer.vf.Source", "modulename": "vidformer.vf", "qualname": "Source", "kind": "class", "doc": "

A video source.

\n"}, "vidformer.vf.Source.__init__": {"fullname": "vidformer.vf.Source.__init__", "modulename": "vidformer.vf", "qualname": "Source.__init__", "kind": "function", "doc": "

\n", "signature": "(\tserver: vidformer.vf.YrdenServer,\tname: str,\tpath: str,\tstream: int,\tservice=None)"}, "vidformer.vf.Source.iloc": {"fullname": "vidformer.vf.Source.iloc", "modulename": "vidformer.vf", "qualname": "Source.iloc", "kind": "variable", "doc": "

\n"}, "vidformer.vf.Source.fmt": {"fullname": "vidformer.vf.Source.fmt", "modulename": "vidformer.vf", "qualname": "Source.fmt", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.vf.Source.ts": {"fullname": "vidformer.vf.Source.ts", "modulename": "vidformer.vf", "qualname": "Source.ts", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.vf.Source.play": {"fullname": "vidformer.vf.Source.play", "modulename": "vidformer.vf", "qualname": "Source.play", "kind": "function", "doc": "

Play the video live in the notebook.

\n", "signature": "(self, *args, **kwargs):", "funcdef": "def"}, "vidformer.vf.StorageService": {"fullname": "vidformer.vf.StorageService", "modulename": "vidformer.vf", "qualname": "StorageService", "kind": "class", "doc": "

\n"}, "vidformer.vf.StorageService.__init__": {"fullname": "vidformer.vf.StorageService.__init__", "modulename": "vidformer.vf", "qualname": "StorageService.__init__", "kind": "function", "doc": "

\n", "signature": "(service: str, **kwargs)"}, "vidformer.vf.StorageService.as_json": {"fullname": "vidformer.vf.StorageService.as_json", "modulename": "vidformer.vf", "qualname": "StorageService.as_json", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.vf.Filter": {"fullname": "vidformer.vf.Filter", "modulename": "vidformer.vf", "qualname": "Filter", "kind": "class", "doc": "

A video filter.

\n"}, "vidformer.vf.Filter.__init__": {"fullname": "vidformer.vf.Filter.__init__", "modulename": "vidformer.vf", "qualname": "Filter.__init__", "kind": "function", "doc": "

\n", "signature": "(name: str, tl_func=None, **kwargs)"}, "vidformer.vf.FilterExpr": {"fullname": "vidformer.vf.FilterExpr", "modulename": "vidformer.vf", "qualname": "FilterExpr", "kind": "class", "doc": "

\n"}, "vidformer.vf.FilterExpr.__init__": {"fullname": "vidformer.vf.FilterExpr.__init__", "modulename": "vidformer.vf", "qualname": "FilterExpr.__init__", "kind": "function", "doc": "

\n", "signature": "(filter: vidformer.vf.Filter, args, kwargs)"}, "vidformer.vf.UDF": {"fullname": "vidformer.vf.UDF", "modulename": "vidformer.vf", "qualname": "UDF", "kind": "class", "doc": "

User-defined filter superclass

\n"}, "vidformer.vf.UDF.__init__": {"fullname": "vidformer.vf.UDF.__init__", "modulename": "vidformer.vf", "qualname": "UDF.__init__", "kind": "function", "doc": "

\n", "signature": "(name: str)"}, "vidformer.vf.UDF.filter": {"fullname": "vidformer.vf.UDF.filter", "modulename": "vidformer.vf", "qualname": "UDF.filter", "kind": "function", "doc": "

\n", "signature": "(self, *args, **kwargs):", "funcdef": "def"}, "vidformer.vf.UDF.filter_type": {"fullname": "vidformer.vf.UDF.filter_type", "modulename": "vidformer.vf", "qualname": "UDF.filter_type", "kind": "function", "doc": "

\n", "signature": "(self, *args, **kwargs):", "funcdef": "def"}, "vidformer.vf.UDF.into_filter": {"fullname": "vidformer.vf.UDF.into_filter", "modulename": "vidformer.vf", "qualname": "UDF.into_filter", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.vf.UDFFrameType": {"fullname": "vidformer.vf.UDFFrameType", "modulename": "vidformer.vf", "qualname": "UDFFrameType", "kind": "class", "doc": "

Frame type for use in UDFs.

\n"}, "vidformer.vf.UDFFrameType.__init__": {"fullname": "vidformer.vf.UDFFrameType.__init__", "modulename": "vidformer.vf", "qualname": "UDFFrameType.__init__", "kind": "function", "doc": "

\n", "signature": "(width: int, height: int, pix_fmt: str)"}, "vidformer.vf.UDFFrameType.width": {"fullname": "vidformer.vf.UDFFrameType.width", "modulename": "vidformer.vf", "qualname": "UDFFrameType.width", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.vf.UDFFrameType.height": {"fullname": "vidformer.vf.UDFFrameType.height", "modulename": "vidformer.vf", "qualname": "UDFFrameType.height", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.vf.UDFFrameType.pix_fmt": {"fullname": "vidformer.vf.UDFFrameType.pix_fmt", "modulename": "vidformer.vf", "qualname": "UDFFrameType.pix_fmt", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.vf.UDFFrame": {"fullname": "vidformer.vf.UDFFrame", "modulename": "vidformer.vf", "qualname": "UDFFrame", "kind": "class", "doc": "

A symbolic reference to a frame for use in UDFs.

\n"}, "vidformer.vf.UDFFrame.__init__": {"fullname": "vidformer.vf.UDFFrame.__init__", "modulename": "vidformer.vf", "qualname": "UDFFrame.__init__", "kind": "function", "doc": "

\n", "signature": "(data: numpy.ndarray, f_type: vidformer.vf.UDFFrameType)"}, "vidformer.vf.UDFFrame.data": {"fullname": "vidformer.vf.UDFFrame.data", "modulename": "vidformer.vf", "qualname": "UDFFrame.data", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, "vidformer.vf.UDFFrame.frame_type": {"fullname": "vidformer.vf.UDFFrame.frame_type", "modulename": "vidformer.vf", "qualname": "UDFFrame.frame_type", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}}, "docInfo": {"vidformer.vf": {"qualname": 0, "fullname": 2, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 53}, "vidformer.vf.Spec": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 20}, "vidformer.vf.Spec.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 40, "bases": 0, "doc": 3}, "vidformer.vf.Spec.play": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 40, "bases": 0, "doc": 10}, "vidformer.vf.Spec.load": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 16, "bases": 0, "doc": 3}, "vidformer.vf.Spec.save": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 52, "bases": 0, "doc": 9}, "vidformer.vf.Loader": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "vidformer.vf.Loader.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 24, "bases": 0, "doc": 3}, "vidformer.vf.YrdenServer": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 24}, "vidformer.vf.YrdenServer.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 45, "bases": 0, "doc": 48}, "vidformer.vf.YrdenServer.hls_js_url": {"qualname": 4, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 12}, "vidformer.vf.SourceExpr": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "vidformer.vf.SourceExpr.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 3}, "vidformer.vf.SourceILoc": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "vidformer.vf.SourceILoc.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 9, "bases": 0, "doc": 3}, "vidformer.vf.Source": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 6}, "vidformer.vf.Source.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 69, "bases": 0, "doc": 3}, "vidformer.vf.Source.iloc": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "vidformer.vf.Source.fmt": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.vf.Source.ts": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.vf.Source.play": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 25, "bases": 0, "doc": 10}, "vidformer.vf.StorageService": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "vidformer.vf.StorageService.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 21, "bases": 0, "doc": 3}, "vidformer.vf.StorageService.as_json": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.vf.Filter": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 6}, "vidformer.vf.Filter.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 32, "bases": 0, "doc": 3}, "vidformer.vf.FilterExpr": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "vidformer.vf.FilterExpr.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 34, "bases": 0, "doc": 3}, "vidformer.vf.UDF": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 6}, "vidformer.vf.UDF.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 3}, "vidformer.vf.UDF.filter": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 25, "bases": 0, "doc": 3}, "vidformer.vf.UDF.filter_type": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 25, "bases": 0, "doc": 3}, "vidformer.vf.UDF.into_filter": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.vf.UDFFrameType": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 9}, "vidformer.vf.UDFFrameType.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 35, "bases": 0, "doc": 3}, "vidformer.vf.UDFFrameType.width": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.vf.UDFFrameType.height": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.vf.UDFFrameType.pix_fmt": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.vf.UDFFrame": {"qualname": 1, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 13}, "vidformer.vf.UDFFrame.__init__": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 40, "bases": 0, "doc": 3}, "vidformer.vf.UDFFrame.data": {"qualname": 2, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}, "vidformer.vf.UDFFrame.frame_type": {"qualname": 3, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 11, "bases": 0, "doc": 3}}, "length": 42, "save": true}, "index": {"qualname": {"root": {"docs": {"vidformer.vf.Spec.__init__": {"tf": 1}, "vidformer.vf.Loader.__init__": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1}, "vidformer.vf.SourceExpr.__init__": {"tf": 1}, "vidformer.vf.SourceILoc.__init__": {"tf": 1}, "vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.StorageService.__init__": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}, "vidformer.vf.UDF.__init__": {"tf": 1}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1}, "vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 12, "s": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.vf.Spec": {"tf": 1}, "vidformer.vf.Spec.__init__": {"tf": 1}, "vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Spec.load": {"tf": 1}, "vidformer.vf.Spec.save": {"tf": 1}}, "df": 5}}}, "a": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Spec.save": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Source": {"tf": 1}, "vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.Source.iloc": {"tf": 1}, "vidformer.vf.Source.fmt": {"tf": 1}, "vidformer.vf.Source.ts": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}}, "df": 6, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.SourceExpr": {"tf": 1}, "vidformer.vf.SourceExpr.__init__": {"tf": 1}}, "df": 2}}}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.vf.SourceILoc": {"tf": 1}, "vidformer.vf.SourceILoc.__init__": {"tf": 1}}, "df": 2}}}}}}}}}, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.StorageService": {"tf": 1}, "vidformer.vf.StorageService.__init__": {"tf": 1}, "vidformer.vf.StorageService.as_json": {"tf": 1}}, "df": 3}}}}}}}}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.Spec.__init__": {"tf": 1}, "vidformer.vf.Loader.__init__": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1}, "vidformer.vf.SourceExpr.__init__": {"tf": 1}, "vidformer.vf.SourceILoc.__init__": {"tf": 1}, "vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.StorageService.__init__": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}, "vidformer.vf.UDF.__init__": {"tf": 1}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1}, "vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 12}}, "t": {"docs": {}, "df": 0, "o": {"docs": {"vidformer.vf.UDF.into_filter": {"tf": 1}}, "df": 1}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.vf.Source.iloc": {"tf": 1}}, "df": 1}}}}, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}}, "df": 2}}}, "i": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.vf.UDFFrameType.pix_fmt": {"tf": 1}}, "df": 1}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.vf.Spec.load": {"tf": 1}}, "df": 1, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.Loader": {"tf": 1}, "vidformer.vf.Loader.__init__": {"tf": 1}}, "df": 2}}}}}}, "y": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.YrdenServer": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1}, "vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 3}}}}}}}}}}}, "h": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 1}}, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.UDFFrameType.height": {"tf": 1}}, "df": 1}}}}}}, "j": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 1, "o": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.StorageService.as_json": {"tf": 1}}, "df": 1}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "l": {"docs": {"vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 1}}, "d": {"docs": {}, "df": 0, "f": {"docs": {"vidformer.vf.UDF": {"tf": 1}, "vidformer.vf.UDF.__init__": {"tf": 1}, "vidformer.vf.UDF.filter": {"tf": 1}, "vidformer.vf.UDF.filter_type": {"tf": 1}, "vidformer.vf.UDF.into_filter": {"tf": 1}}, "df": 5, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDFFrame": {"tf": 1}, "vidformer.vf.UDFFrame.__init__": {"tf": 1}, "vidformer.vf.UDFFrame.data": {"tf": 1}, "vidformer.vf.UDFFrame.frame_type": {"tf": 1}}, "df": 4, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDFFrameType": {"tf": 1}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1}, "vidformer.vf.UDFFrameType.width": {"tf": 1}, "vidformer.vf.UDFFrameType.height": {"tf": 1}, "vidformer.vf.UDFFrameType.pix_fmt": {"tf": 1}}, "df": 5}}}}}}}}}}}}, "f": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.Source.fmt": {"tf": 1}, "vidformer.vf.UDFFrameType.pix_fmt": {"tf": 1}}, "df": 2}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.Filter": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}, "vidformer.vf.UDF.filter": {"tf": 1}, "vidformer.vf.UDF.filter_type": {"tf": 1}, "vidformer.vf.UDF.into_filter": {"tf": 1}}, "df": 5, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.FilterExpr": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}}, "df": 2}}}}}}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDFFrame.frame_type": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.Source.ts": {"tf": 1}}, "df": 1}, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDF.filter_type": {"tf": 1}, "vidformer.vf.UDFFrame.frame_type": {"tf": 1}}, "df": 2}}}}, "a": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.StorageService.as_json": {"tf": 1}}, "df": 1}}, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"vidformer.vf.UDFFrameType.width": {"tf": 1}}, "df": 1}}}}}, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"vidformer.vf.UDFFrame.data": {"tf": 1}}, "df": 1}}}}}}, "fullname": {"root": {"docs": {"vidformer.vf.Spec.__init__": {"tf": 1}, "vidformer.vf.Loader.__init__": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1}, "vidformer.vf.SourceExpr.__init__": {"tf": 1}, "vidformer.vf.SourceILoc.__init__": {"tf": 1}, "vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.StorageService.__init__": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}, "vidformer.vf.UDF.__init__": {"tf": 1}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1}, "vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 12, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf": {"tf": 1}, "vidformer.vf.Spec": {"tf": 1}, "vidformer.vf.Spec.__init__": {"tf": 1}, "vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Spec.load": {"tf": 1}, "vidformer.vf.Spec.save": {"tf": 1}, "vidformer.vf.Loader": {"tf": 1}, "vidformer.vf.Loader.__init__": {"tf": 1}, "vidformer.vf.YrdenServer": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1}, "vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}, "vidformer.vf.SourceExpr": {"tf": 1}, "vidformer.vf.SourceExpr.__init__": {"tf": 1}, "vidformer.vf.SourceILoc": {"tf": 1}, "vidformer.vf.SourceILoc.__init__": {"tf": 1}, "vidformer.vf.Source": {"tf": 1}, "vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.Source.iloc": {"tf": 1}, "vidformer.vf.Source.fmt": {"tf": 1}, "vidformer.vf.Source.ts": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}, "vidformer.vf.StorageService": {"tf": 1}, "vidformer.vf.StorageService.__init__": {"tf": 1}, "vidformer.vf.StorageService.as_json": {"tf": 1}, "vidformer.vf.Filter": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}, "vidformer.vf.FilterExpr": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}, "vidformer.vf.UDF": {"tf": 1}, "vidformer.vf.UDF.__init__": {"tf": 1}, "vidformer.vf.UDF.filter": {"tf": 1}, "vidformer.vf.UDF.filter_type": {"tf": 1}, "vidformer.vf.UDF.into_filter": {"tf": 1}, "vidformer.vf.UDFFrameType": {"tf": 1}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1}, "vidformer.vf.UDFFrameType.width": {"tf": 1}, "vidformer.vf.UDFFrameType.height": {"tf": 1}, "vidformer.vf.UDFFrameType.pix_fmt": {"tf": 1}, "vidformer.vf.UDFFrame": {"tf": 1}, "vidformer.vf.UDFFrame.__init__": {"tf": 1}, "vidformer.vf.UDFFrame.data": {"tf": 1}, "vidformer.vf.UDFFrame.frame_type": {"tf": 1}}, "df": 42}}}}}}}}, "f": {"docs": {"vidformer.vf": {"tf": 1}, "vidformer.vf.Spec": {"tf": 1}, "vidformer.vf.Spec.__init__": {"tf": 1}, "vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Spec.load": {"tf": 1}, "vidformer.vf.Spec.save": {"tf": 1}, "vidformer.vf.Loader": {"tf": 1}, "vidformer.vf.Loader.__init__": {"tf": 1}, "vidformer.vf.YrdenServer": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1}, "vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}, "vidformer.vf.SourceExpr": {"tf": 1}, "vidformer.vf.SourceExpr.__init__": {"tf": 1}, "vidformer.vf.SourceILoc": {"tf": 1}, "vidformer.vf.SourceILoc.__init__": {"tf": 1}, "vidformer.vf.Source": {"tf": 1}, "vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.Source.iloc": {"tf": 1}, "vidformer.vf.Source.fmt": {"tf": 1}, "vidformer.vf.Source.ts": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}, "vidformer.vf.StorageService": {"tf": 1}, "vidformer.vf.StorageService.__init__": {"tf": 1}, "vidformer.vf.StorageService.as_json": {"tf": 1}, "vidformer.vf.Filter": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}, "vidformer.vf.FilterExpr": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}, "vidformer.vf.UDF": {"tf": 1}, "vidformer.vf.UDF.__init__": {"tf": 1}, "vidformer.vf.UDF.filter": {"tf": 1}, "vidformer.vf.UDF.filter_type": {"tf": 1}, "vidformer.vf.UDF.into_filter": {"tf": 1}, "vidformer.vf.UDFFrameType": {"tf": 1}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1}, "vidformer.vf.UDFFrameType.width": {"tf": 1}, "vidformer.vf.UDFFrameType.height": {"tf": 1}, "vidformer.vf.UDFFrameType.pix_fmt": {"tf": 1}, "vidformer.vf.UDFFrame": {"tf": 1}, "vidformer.vf.UDFFrame.__init__": {"tf": 1}, "vidformer.vf.UDFFrame.data": {"tf": 1}, "vidformer.vf.UDFFrame.frame_type": {"tf": 1}}, "df": 42}}, "s": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.vf.Spec": {"tf": 1}, "vidformer.vf.Spec.__init__": {"tf": 1}, "vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Spec.load": {"tf": 1}, "vidformer.vf.Spec.save": {"tf": 1}}, "df": 5}}}, "a": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Spec.save": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Source": {"tf": 1}, "vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.Source.iloc": {"tf": 1}, "vidformer.vf.Source.fmt": {"tf": 1}, "vidformer.vf.Source.ts": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}}, "df": 6, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.SourceExpr": {"tf": 1}, "vidformer.vf.SourceExpr.__init__": {"tf": 1}}, "df": 2}}}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.vf.SourceILoc": {"tf": 1}, "vidformer.vf.SourceILoc.__init__": {"tf": 1}}, "df": 2}}}}}}}}}, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.StorageService": {"tf": 1}, "vidformer.vf.StorageService.__init__": {"tf": 1}, "vidformer.vf.StorageService.as_json": {"tf": 1}}, "df": 3}}}}}}}}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.Spec.__init__": {"tf": 1}, "vidformer.vf.Loader.__init__": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1}, "vidformer.vf.SourceExpr.__init__": {"tf": 1}, "vidformer.vf.SourceILoc.__init__": {"tf": 1}, "vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.StorageService.__init__": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}, "vidformer.vf.UDF.__init__": {"tf": 1}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1}, "vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 12}}, "t": {"docs": {}, "df": 0, "o": {"docs": {"vidformer.vf.UDF.into_filter": {"tf": 1}}, "df": 1}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.vf.Source.iloc": {"tf": 1}}, "df": 1}}}}, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}}, "df": 2}}}, "i": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.vf.UDFFrameType.pix_fmt": {"tf": 1}}, "df": 1}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.vf.Spec.load": {"tf": 1}}, "df": 1, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.Loader": {"tf": 1}, "vidformer.vf.Loader.__init__": {"tf": 1}}, "df": 2}}}}}}, "y": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.YrdenServer": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1}, "vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 3}}}}}}}}}}}, "h": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 1}}, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.UDFFrameType.height": {"tf": 1}}, "df": 1}}}}}}, "j": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 1, "o": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.StorageService.as_json": {"tf": 1}}, "df": 1}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "l": {"docs": {"vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 1}}, "d": {"docs": {}, "df": 0, "f": {"docs": {"vidformer.vf.UDF": {"tf": 1}, "vidformer.vf.UDF.__init__": {"tf": 1}, "vidformer.vf.UDF.filter": {"tf": 1}, "vidformer.vf.UDF.filter_type": {"tf": 1}, "vidformer.vf.UDF.into_filter": {"tf": 1}}, "df": 5, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDFFrame": {"tf": 1}, "vidformer.vf.UDFFrame.__init__": {"tf": 1}, "vidformer.vf.UDFFrame.data": {"tf": 1}, "vidformer.vf.UDFFrame.frame_type": {"tf": 1}}, "df": 4, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDFFrameType": {"tf": 1}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1}, "vidformer.vf.UDFFrameType.width": {"tf": 1}, "vidformer.vf.UDFFrameType.height": {"tf": 1}, "vidformer.vf.UDFFrameType.pix_fmt": {"tf": 1}}, "df": 5}}}}}}}}}}}}, "f": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.Source.fmt": {"tf": 1}, "vidformer.vf.UDFFrameType.pix_fmt": {"tf": 1}}, "df": 2}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.Filter": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}, "vidformer.vf.UDF.filter": {"tf": 1}, "vidformer.vf.UDF.filter_type": {"tf": 1}, "vidformer.vf.UDF.into_filter": {"tf": 1}}, "df": 5, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.FilterExpr": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}}, "df": 2}}}}}}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDFFrame.frame_type": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.Source.ts": {"tf": 1}}, "df": 1}, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDF.filter_type": {"tf": 1}, "vidformer.vf.UDFFrame.frame_type": {"tf": 1}}, "df": 2}}}}, "a": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.StorageService.as_json": {"tf": 1}}, "df": 1}}, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"vidformer.vf.UDFFrameType.width": {"tf": 1}}, "df": 1}}}}}, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"vidformer.vf.UDFFrame.data": {"tf": 1}}, "df": 1}}}}}}, "annotation": {"root": {"docs": {}, "df": 0}}, "default_value": {"root": {"docs": {}, "df": 0}}, "signature": {"root": {"3": {"9": {"docs": {"vidformer.vf.Spec.play": {"tf": 1.4142135623730951}}, "df": 1}, "docs": {}, "df": 0}, "docs": {"vidformer.vf.Spec.__init__": {"tf": 5.744562646538029}, "vidformer.vf.Spec.play": {"tf": 5.656854249492381}, "vidformer.vf.Spec.load": {"tf": 3.7416573867739413}, "vidformer.vf.Spec.save": {"tf": 6.48074069840786}, "vidformer.vf.Loader.__init__": {"tf": 4.47213595499958}, "vidformer.vf.YrdenServer.__init__": {"tf": 6}, "vidformer.vf.YrdenServer.hls_js_url": {"tf": 3.1622776601683795}, "vidformer.vf.SourceExpr.__init__": {"tf": 4}, "vidformer.vf.SourceILoc.__init__": {"tf": 2.8284271247461903}, "vidformer.vf.Source.__init__": {"tf": 7.54983443527075}, "vidformer.vf.Source.fmt": {"tf": 3.1622776601683795}, "vidformer.vf.Source.ts": {"tf": 3.1622776601683795}, "vidformer.vf.Source.play": {"tf": 4.69041575982343}, "vidformer.vf.StorageService.__init__": {"tf": 4.242640687119285}, "vidformer.vf.StorageService.as_json": {"tf": 3.1622776601683795}, "vidformer.vf.Filter.__init__": {"tf": 5.0990195135927845}, "vidformer.vf.FilterExpr.__init__": {"tf": 5.291502622129181}, "vidformer.vf.UDF.__init__": {"tf": 3.4641016151377544}, "vidformer.vf.UDF.filter": {"tf": 4.69041575982343}, "vidformer.vf.UDF.filter_type": {"tf": 4.69041575982343}, "vidformer.vf.UDF.into_filter": {"tf": 3.1622776601683795}, "vidformer.vf.UDFFrameType.__init__": {"tf": 5.291502622129181}, "vidformer.vf.UDFFrameType.width": {"tf": 3.1622776601683795}, "vidformer.vf.UDFFrameType.height": {"tf": 3.1622776601683795}, "vidformer.vf.UDFFrameType.pix_fmt": {"tf": 3.1622776601683795}, "vidformer.vf.UDFFrame.__init__": {"tf": 5.656854249492381}, "vidformer.vf.UDFFrame.data": {"tf": 3.1622776601683795}, "vidformer.vf.UDFFrame.frame_type": {"tf": 3.1622776601683795}}, "df": 28, "d": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.Spec.__init__": {"tf": 1}, "vidformer.vf.Loader.__init__": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 3}}}}}, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.Spec.__init__": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 1}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.Spec.__init__": {"tf": 1}}, "df": 1}}}}, "f": {"docs": {"vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 1, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.Spec.__init__": {"tf": 1}}, "df": 1, "s": {"docs": {"vidformer.vf.Spec.__init__": {"tf": 1}}, "df": 1}}}}}}}}, "m": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.Spec.__init__": {"tf": 1}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1}}, "df": 2}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}}, "df": 1}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.Spec.save": {"tf": 1}}, "df": 1}}}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.vf.Filter.__init__": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.FilterExpr.__init__": {"tf": 1.4142135623730951}}, "df": 1}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.Spec.__init__": {"tf": 1}}, "df": 1}}}}}}, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "f": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Spec.load": {"tf": 1}, "vidformer.vf.Spec.save": {"tf": 1}, "vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}, "vidformer.vf.Source.fmt": {"tf": 1}, "vidformer.vf.Source.ts": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}, "vidformer.vf.StorageService.as_json": {"tf": 1}, "vidformer.vf.UDF.filter": {"tf": 1}, "vidformer.vf.UDF.filter_type": {"tf": 1}, "vidformer.vf.UDF.into_filter": {"tf": 1}, "vidformer.vf.UDFFrameType.width": {"tf": 1}, "vidformer.vf.UDFFrameType.height": {"tf": 1}, "vidformer.vf.UDFFrameType.pix_fmt": {"tf": 1}, "vidformer.vf.UDFFrame.data": {"tf": 1}, "vidformer.vf.UDFFrame.frame_type": {"tf": 1}}, "df": 16}}, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Spec.load": {"tf": 1}, "vidformer.vf.Spec.save": {"tf": 1}, "vidformer.vf.Loader.__init__": {"tf": 1}, "vidformer.vf.Source.__init__": {"tf": 1}}, "df": 5}}, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.StorageService.__init__": {"tf": 1}}, "df": 2}}}}}}, "t": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.Loader.__init__": {"tf": 1}, "vidformer.vf.Source.__init__": {"tf": 1.4142135623730951}, "vidformer.vf.StorageService.__init__": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}, "vidformer.vf.UDF.__init__": {"tf": 1}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1}}, "df": 6, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {"vidformer.vf.Source.__init__": {"tf": 1}}, "df": 1}}}}}, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.SourceExpr.__init__": {"tf": 1}, "vidformer.vf.SourceILoc.__init__": {"tf": 1}}, "df": 2}}}}}}, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}}, "df": 1}}}}}}, "h": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "l": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}}, "df": 1}}}, "l": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.UDFFrameType.__init__": {"tf": 1}}, "df": 1}}}}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}}, "df": 1}}}}}}, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}, "vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 3}}}}}}}}, "f": {"docs": {"vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}, "vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 3}}, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"vidformer.vf.Spec.save": {"tf": 1}}, "df": 1}}, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"vidformer.vf.Source.__init__": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.vf.UDFFrameType.__init__": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.Spec.save": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}, "n": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Spec.save": {"tf": 1.7320508075688772}, "vidformer.vf.YrdenServer.__init__": {"tf": 2}, "vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}}, "df": 4}}}, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}, "vidformer.vf.UDF.__init__": {"tf": 1}}, "df": 3, "s": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Loader.__init__": {"tf": 1}}, "df": 1}}}}}}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 1}}}}}}}, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.Spec.save": {"tf": 1}}, "df": 1}}}}, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "x": {"docs": {"vidformer.vf.SourceExpr.__init__": {"tf": 1}}, "df": 1}}, "s": {"docs": {"vidformer.vf.SourceExpr.__init__": {"tf": 1}}, "df": 1}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.vf.SourceExpr.__init__": {"tf": 1}}, "df": 1}}}, "n": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.Source.__init__": {"tf": 1}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1.4142135623730951}}, "df": 2}}}, "y": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.Source.__init__": {"tf": 1}}, "df": 1}}}}}}}}}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.Source.play": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}, "vidformer.vf.UDF.filter": {"tf": 1}, "vidformer.vf.UDF.filter_type": {"tf": 1}}, "df": 4}}}}, "k": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.Source.play": {"tf": 1}, "vidformer.vf.StorageService.__init__": {"tf": 1}, "vidformer.vf.Filter.__init__": {"tf": 1}, "vidformer.vf.FilterExpr.__init__": {"tf": 1}, "vidformer.vf.UDF.filter": {"tf": 1}, "vidformer.vf.UDF.filter_type": {"tf": 1}}, "df": 6}}}}}}, "t": {"docs": {}, "df": 0, "l": {"docs": {"vidformer.vf.Filter.__init__": {"tf": 1}}, "df": 1}, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 1}}}}, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"vidformer.vf.UDFFrameType.__init__": {"tf": 1}}, "df": 1}}}}}, "u": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDFFrame.__init__": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}, "bases": {"root": {"docs": {}, "df": 0}}, "doc": {"root": {"docs": {"vidformer.vf": {"tf": 5.830951894845301}, "vidformer.vf.Spec": {"tf": 2.8284271247461903}, "vidformer.vf.Spec.__init__": {"tf": 1.7320508075688772}, "vidformer.vf.Spec.play": {"tf": 1.7320508075688772}, "vidformer.vf.Spec.load": {"tf": 1.7320508075688772}, "vidformer.vf.Spec.save": {"tf": 1.7320508075688772}, "vidformer.vf.Loader": {"tf": 1.7320508075688772}, "vidformer.vf.Loader.__init__": {"tf": 1.7320508075688772}, "vidformer.vf.YrdenServer": {"tf": 2.449489742783178}, "vidformer.vf.YrdenServer.__init__": {"tf": 2.6457513110645907}, "vidformer.vf.YrdenServer.hls_js_url": {"tf": 1.4142135623730951}, "vidformer.vf.SourceExpr": {"tf": 1.7320508075688772}, "vidformer.vf.SourceExpr.__init__": {"tf": 1.7320508075688772}, "vidformer.vf.SourceILoc": {"tf": 1.7320508075688772}, "vidformer.vf.SourceILoc.__init__": {"tf": 1.7320508075688772}, "vidformer.vf.Source": {"tf": 1.7320508075688772}, "vidformer.vf.Source.__init__": {"tf": 1.7320508075688772}, "vidformer.vf.Source.iloc": {"tf": 1.7320508075688772}, "vidformer.vf.Source.fmt": {"tf": 1.7320508075688772}, "vidformer.vf.Source.ts": {"tf": 1.7320508075688772}, "vidformer.vf.Source.play": {"tf": 1.7320508075688772}, "vidformer.vf.StorageService": {"tf": 1.7320508075688772}, "vidformer.vf.StorageService.__init__": {"tf": 1.7320508075688772}, "vidformer.vf.StorageService.as_json": {"tf": 1.7320508075688772}, "vidformer.vf.Filter": {"tf": 1.7320508075688772}, "vidformer.vf.Filter.__init__": {"tf": 1.7320508075688772}, "vidformer.vf.FilterExpr": {"tf": 1.7320508075688772}, "vidformer.vf.FilterExpr.__init__": {"tf": 1.7320508075688772}, "vidformer.vf.UDF": {"tf": 1.4142135623730951}, "vidformer.vf.UDF.__init__": {"tf": 1.7320508075688772}, "vidformer.vf.UDF.filter": {"tf": 1.7320508075688772}, "vidformer.vf.UDF.filter_type": {"tf": 1.7320508075688772}, "vidformer.vf.UDF.into_filter": {"tf": 1.7320508075688772}, "vidformer.vf.UDFFrameType": {"tf": 1.7320508075688772}, "vidformer.vf.UDFFrameType.__init__": {"tf": 1.7320508075688772}, "vidformer.vf.UDFFrameType.width": {"tf": 1.7320508075688772}, "vidformer.vf.UDFFrameType.height": {"tf": 1.7320508075688772}, "vidformer.vf.UDFFrameType.pix_fmt": {"tf": 1.7320508075688772}, "vidformer.vf.UDFFrame": {"tf": 1.7320508075688772}, "vidformer.vf.UDFFrame.__init__": {"tf": 1.7320508075688772}, "vidformer.vf.UDFFrame.data": {"tf": 1.7320508075688772}, "vidformer.vf.UDFFrame.frame_type": {"tf": 1.7320508075688772}}, "df": 42, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf": {"tf": 2}, "vidformer.vf.YrdenServer": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 3}}}}}}, "e": {"docs": {}, "df": 0, "o": {"docs": {"vidformer.vf.Spec": {"tf": 1}, "vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Spec.save": {"tf": 1}, "vidformer.vf.Source": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}, "vidformer.vf.Filter": {"tf": 1}}, "df": 6}}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}}}}}}, "p": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.vf": {"tf": 1.4142135623730951}}, "df": 1, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf": {"tf": 1}}, "df": 1}}}}, "p": {"docs": {}, "df": 0, "i": {"docs": {"vidformer.vf": {"tf": 1}}, "df": 1}}}, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}}, "df": 2}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1.7320508075688772}}, "df": 1}}}}}}}}, "i": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf": {"tf": 1}, "vidformer.vf.YrdenServer": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1.4142135623730951}}, "df": 3}, "n": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}, "vidformer.vf.UDFFrameType": {"tf": 1}, "vidformer.vf.UDFFrame": {"tf": 1}}, "df": 4, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf": {"tf": 1}}, "df": 1}}}}}}}, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.Spec": {"tf": 1}}, "df": 1}}}}}}}}}}, "o": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.Spec": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}}}}}}}, "f": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1.4142135623730951}}, "df": 1}}, "a": {"docs": {"vidformer.vf": {"tf": 1}, "vidformer.vf.Spec": {"tf": 1}, "vidformer.vf.Spec.save": {"tf": 1}, "vidformer.vf.YrdenServer": {"tf": 1.7320508075688772}, "vidformer.vf.YrdenServer.__init__": {"tf": 1.4142135623730951}, "vidformer.vf.Source": {"tf": 1}, "vidformer.vf.Filter": {"tf": 1}, "vidformer.vf.UDFFrame": {"tf": 1.4142135623730951}}, "df": 8, "p": {"docs": {}, "df": 0, "i": {"docs": {"vidformer.vf.YrdenServer": {"tf": 1}}, "df": 1}}, "n": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1, "d": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}, "r": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf": {"tf": 1}, "vidformer.vf.Spec": {"tf": 1}, "vidformer.vf.YrdenServer": {"tf": 1}, "vidformer.vf.UDFFrameType": {"tf": 1}, "vidformer.vf.UDFFrame": {"tf": 1}}, "df": 5}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Spec.save": {"tf": 1}, "vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 2}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.Filter": {"tf": 1}, "vidformer.vf.UDF": {"tf": 1}}, "df": 2}}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDFFrameType": {"tf": 1}, "vidformer.vf.UDFFrame": {"tf": 1}}, "df": 2}}}}}, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"vidformer.vf": {"tf": 1}}, "df": 1}}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "k": {"docs": {"vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 1, "s": {"docs": {"vidformer.vf": {"tf": 1}}, "df": 1}}}, "v": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}}, "df": 2}}}, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"vidformer.vf.YrdenServer": {"tf": 1}}, "df": 1}}}}}, "d": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}}}}, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "e": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.vf.UDF": {"tf": 1}}, "df": 1}}}}}}}, "c": {"docs": {}, "df": 0, "v": {"2": {"docs": {"vidformer.vf": {"tf": 1}}, "df": 1}, "docs": {}, "df": 0}, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf": {"tf": 1}}, "df": 1}}, "n": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1.4142135623730951}}, "df": 1, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.YrdenServer": {"tf": 1}}, "df": 1}}}}}}}}}, "a": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}, "s": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf": {"tf": 1}, "vidformer.vf.Source": {"tf": 1}}, "df": 2}}}}}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.Spec": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "e": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Spec": {"tf": 1}}, "df": 1}, "r": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.YrdenServer": {"tf": 1.4142135623730951}, "vidformer.vf.YrdenServer.__init__": {"tf": 1.7320508075688772}}, "df": 2}}}}}, "a": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Spec.save": {"tf": 1}}, "df": 1}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}}, "u": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.UDF": {"tf": 1}}, "df": 1}}}}}}}}}, "y": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {"vidformer.vf.UDFFrame": {"tf": 1}}, "df": 1}}}}}}}}, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.Spec": {"tf": 1}}, "df": 1}}}}}}}}}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Spec.play": {"tf": 1.4142135623730951}, "vidformer.vf.Spec.save": {"tf": 1}, "vidformer.vf.YrdenServer": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1.4142135623730951}, "vidformer.vf.YrdenServer.hls_js_url": {"tf": 1.4142135623730951}, "vidformer.vf.Source.play": {"tf": 1.4142135623730951}}, "df": 6}}, "o": {"docs": {"vidformer.vf.Spec.save": {"tf": 1}, "vidformer.vf.YrdenServer": {"tf": 1}, "vidformer.vf.YrdenServer.__init__": {"tf": 1.4142135623730951}, "vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}, "vidformer.vf.UDFFrame": {"tf": 1}}, "df": 5}, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDFFrameType": {"tf": 1}}, "df": 1}}}}, "h": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, ":": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "/": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {"vidformer.vf.Spec": {"tf": 1}}, "df": 1}}}}}}}}}}}, "m": {"docs": {}, "df": 0, "l": {"docs": {"vidformer.vf.Spec": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 1}}}}}, "l": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 1}}}, "g": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "b": {"docs": {"vidformer.vf.Spec": {"tf": 1}}, "df": 1}}}}}}, "m": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.Spec": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.YrdenServer": {"tf": 1}}, "df": 1}}}}, "n": {"docs": {}, "df": 0, "o": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "k": {"docs": {"vidformer.vf.Spec.play": {"tf": 1}, "vidformer.vf.Source.play": {"tf": 1}}, "df": 2}}}}}}}, "e": {"docs": {}, "df": 0, "w": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}, "y": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.YrdenServer": {"tf": 1.4142135623730951}, "vidformer.vf.YrdenServer.__init__": {"tf": 1}, "vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 3}}}}}, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.YrdenServer": {"tf": 1}, "vidformer.vf.UDFFrameType": {"tf": 1}, "vidformer.vf.UDFFrame": {"tf": 1}}, "df": 3, "d": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}, "r": {"docs": {"vidformer.vf.UDF": {"tf": 1}}, "df": 1}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.UDFFrameType": {"tf": 1}, "vidformer.vf.UDFFrame": {"tf": 1}}, "df": 2}}}}, "o": {"docs": {}, "df": 0, "f": {"docs": {"vidformer.vf.YrdenServer": {"tf": 1}}, "df": 1}, "r": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1.4142135623730951}}, "df": 1}}, "e": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}}}, "x": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}}}}}, "n": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1}}}}}}}}}}}, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1}}, "df": 1, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"vidformer.vf.YrdenServer.__init__": {"tf": 1.4142135623730951}}, "df": 1}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "n": {"docs": {"vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 1}}}}, "f": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"vidformer.vf.UDFFrame": {"tf": 1}}, "df": 1}}}}}}}}}, "j": {"docs": {}, "df": 0, "s": {"docs": {"vidformer.vf.YrdenServer.hls_js_url": {"tf": 1}}, "df": 1}}}}}, "pipeline": ["trimmer"], "_isPrebuiltIndex": true}; + + // mirrored in build-search-index.js (part 1) + // Also split on html tags. this is a cheap heuristic, but good enough. + elasticlunr.tokenizer.setSeperator(/[\s\-.;&_'"=,()]+|<[^>]*>/); + + let searchIndex; + if (docs._isPrebuiltIndex) { + console.info("using precompiled search index"); + searchIndex = elasticlunr.Index.load(docs); + } else { + console.time("building search index"); + // mirrored in build-search-index.js (part 2) + searchIndex = elasticlunr(function () { + this.pipeline.remove(elasticlunr.stemmer); + this.pipeline.remove(elasticlunr.stopWordFilter); + this.addField("qualname"); + this.addField("fullname"); + this.addField("annotation"); + this.addField("default_value"); + this.addField("signature"); + this.addField("bases"); + this.addField("doc"); + this.setRef("fullname"); + }); + for (let doc of docs) { + searchIndex.addDoc(doc); + } + console.timeEnd("building search index"); + } + + return (term) => searchIndex.search(term, { + fields: { + qualname: {boost: 4}, + fullname: {boost: 2}, + annotation: {boost: 2}, + default_value: {boost: 2}, + signature: {boost: 2}, + bases: {boost: 2}, + doc: {boost: 1}, + }, + expand: true + }); +})(); \ No newline at end of file diff --git a/vidformer-py/vidformer/vf.html b/vidformer-py/vidformer/vf.html new file mode 100644 index 0000000..f6bf39e --- /dev/null +++ b/vidformer-py/vidformer/vf.html @@ -0,0 +1,3117 @@ + + + + + + + vidformer.vf API documentation + + + + + + + + + +
+
+

+vidformer.vf

+ +

vidformer-py is a Python 🐍 interface for vidformer.

+ +

Quick links:

+ + +
+ + + + + +
  1"""
+  2vidformer-py is a Python 🐍 interface for [vidformer](https://github.com/ixlab/vidformer).
+  3
+  4**Quick links:**
+  5* [📦 PyPI](https://pypi.org/project/vidformer/)
+  6* [📘 Documentation - vidformer-py](https://ixlab.github.io/vidformer/vidformer-py/)
+  7* [📘 Documentation - vidformer.cv2](https://ixlab.github.io/vidformer/vidformer-py-cv2/)
+  8* [🧑‍💻 Source Code](https://github.com/ixlab/vidformer/tree/main/vidformer-py/)
+  9"""
+ 10
+ 11import subprocess
+ 12from fractions import Fraction
+ 13import random
+ 14import time
+ 15import json
+ 16import socket
+ 17import os
+ 18import sys
+ 19import multiprocessing
+ 20import uuid
+ 21import threading
+ 22import gzip
+ 23import base64
+ 24import re
+ 25
+ 26import requests
+ 27import msgpack
+ 28import numpy as np
+ 29
+ 30from . import __version__
+ 31
+ 32_in_notebook = False
+ 33try:
+ 34    from IPython import get_ipython
+ 35
+ 36    if "IPKernelApp" in get_ipython().config:
+ 37        _in_notebook = True
+ 38except:
+ 39    pass
+ 40
+ 41
+ 42def _check_hls_link_exists(url, max_attempts=150, delay=0.1):
+ 43    for attempt in range(max_attempts):
+ 44        try:
+ 45            response = requests.get(url)
+ 46            if response.status_code == 200:
+ 47                return response.text.strip()
+ 48            else:
+ 49                time.sleep(delay)
+ 50        except requests.exceptions.RequestException as e:
+ 51            time.sleep(delay)
+ 52    return None
+ 53
+ 54
+ 55class Spec:
+ 56    """
+ 57    A video transformation specification.
+ 58
+ 59    See https://ixlab.github.io/vidformer/concepts.html for more information.
+ 60    """
+ 61
+ 62    def __init__(self, domain: list[Fraction], render, fmt: dict):
+ 63        self._domain = domain
+ 64        self._render = render
+ 65        self._fmt = fmt
+ 66
+ 67    def __repr__(self):
+ 68        if len(self._domain) <= 20:
+ 69            lines = []
+ 70            for i, t in enumerate(self._domain):
+ 71                frame_expr = self._render(t, i)
+ 72                lines.append(
+ 73                    f"{t.numerator}/{t.denominator} => {frame_expr}",
+ 74                )
+ 75            return "\n".join(lines)
+ 76        else:
+ 77            lines = []
+ 78            for i, t in enumerate(self._domain[:10]):
+ 79                frame_expr = self._render(t, i)
+ 80                lines.append(
+ 81                    f"{t.numerator}/{t.denominator} => {frame_expr}",
+ 82                )
+ 83            lines.append("...")
+ 84            for i, t in enumerate(self._domain[-10:]):
+ 85                frame_expr = self._render(t, i)
+ 86                lines.append(
+ 87                    f"{t.numerator}/{t.denominator} => {frame_expr}",
+ 88                )
+ 89            return "\n".join(lines)
+ 90
+ 91    def _sources(self):
+ 92        s = set()
+ 93        for i, t in enumerate(self._domain):
+ 94            frame_expr = self._render(t, i)
+ 95            s = s.union(frame_expr._sources())
+ 96        return s
+ 97
+ 98    def _to_json_spec(self):
+ 99        frames = []
+100        s = set()
+101        f = {}
+102        for i, t in enumerate(self._domain):
+103            frame_expr = self._render(t, i)
+104            s = s.union(frame_expr._sources())
+105            f = {**f, **frame_expr._filters()}
+106            frame = [[t.numerator, t.denominator], frame_expr._to_json_spec()]
+107            frames.append(frame)
+108        return {"frames": frames}, s, f
+109
+110    def play(self, server, method="html", verbose=False):
+111        """Play the video live in the notebook."""
+112
+113        spec, sources, filters = self._to_json_spec()
+114        spec_json_bytes = json.dumps(spec).encode("utf-8")
+115        spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
+116        spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
+117
+118        sources = [
+119            {
+120                "name": s._name,
+121                "path": s._path,
+122                "stream": s._stream,
+123                "service": s._service.as_json() if s._service is not None else None,
+124            }
+125            for s in sources
+126        ]
+127        filters = {
+128            k: {
+129                "filter": v._func,
+130                "args": v._kwargs,
+131            }
+132            for k, v in filters.items()
+133        }
+134        arrays = []
+135
+136        if verbose:
+137            print(f"Sending to server. Spec is {len(spec_obj_json_gzip_b64)} bytes")
+138
+139        resp = server._new(spec_obj_json_gzip_b64, sources, filters, arrays, self._fmt)
+140        hls_video_url = resp["stream_url"]
+141        hls_player_url = resp["player_url"]
+142        namespace = resp["namespace"]
+143        hls_js_url = server.hls_js_url()
+144
+145        if method == "link":
+146            return hls_video_url
+147        if method == "player":
+148            return hls_player_url
+149        if method == "iframe":
+150            from IPython.display import IFrame
+151
+152            return IFrame(hls_player_url, width=1280, height=720)
+153        if method == "html":
+154            from IPython.display import HTML
+155
+156            # We add a namespace to the video element to avoid conflicts with other videos
+157            html_code = f"""
+158<!DOCTYPE html>
+159<html>
+160<head>
+161    <title>HLS Video Player</title>
+162    <!-- Include hls.js library -->
+163    <script src="{hls_js_url}"></script>
+164</head>
+165<body>
+166    <!-- Video element -->
+167    <video id="video-{namespace}" controls width="640" height="360" autoplay></video>
+168    <script>
+169        var video = document.getElementById('video-{namespace}');
+170        var videoSrc = '{hls_video_url}';
+171        var hls = new Hls();
+172        hls.loadSource(videoSrc);
+173        hls.attachMedia(video);
+174        hls.on(Hls.Events.MANIFEST_PARSED, function() {{
+175            video.play();
+176        }});
+177    </script>
+178</body>
+179</html>
+180"""
+181            return HTML(data=html_code)
+182        else:
+183            return hls_player_url
+184
+185    def load(self, server):
+186        spec, sources, filters = self._to_json_spec()
+187        spec_json_bytes = json.dumps(spec).encode("utf-8")
+188        spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
+189        spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
+190
+191        sources = [
+192            {
+193                "name": s._name,
+194                "path": s._path,
+195                "stream": s._stream,
+196                "service": s._service.as_json() if s._service is not None else None,
+197            }
+198            for s in sources
+199        ]
+200        filters = {
+201            k: {
+202                "filter": v._func,
+203                "args": v._kwargs,
+204            }
+205            for k, v in filters.items()
+206        }
+207        arrays = []
+208
+209        resp = server._new(spec_obj_json_gzip_b64, sources, filters, arrays, self._fmt)
+210        namespace = resp["namespace"]
+211        return Loader(server, namespace, self._domain)
+212
+213    def save(self, server, pth, encoder=None, encoder_opts=None, format=None):
+214        """Save the video to a file."""
+215
+216        assert encoder is None or type(encoder) == str
+217        assert encoder_opts is None or type(encoder_opts) == dict
+218        if encoder_opts is not None:
+219            for k, v in encoder_opts.items():
+220                assert type(k) == str and type(v) == str
+221
+222        spec, sources, filters = self._to_json_spec()
+223        spec_json_bytes = json.dumps(spec).encode("utf-8")
+224        spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
+225        spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
+226
+227        sources = [
+228            {
+229                "name": s._name,
+230                "path": s._path,
+231                "stream": s._stream,
+232                "service": s._service.as_json() if s._service is not None else None,
+233            }
+234            for s in sources
+235        ]
+236        filters = {
+237            k: {
+238                "filter": v._func,
+239                "args": v._kwargs,
+240            }
+241            for k, v in filters.items()
+242        }
+243        arrays = []
+244
+245        resp = server._export(
+246            pth,
+247            spec_obj_json_gzip_b64,
+248            sources,
+249            filters,
+250            arrays,
+251            self._fmt,
+252            encoder,
+253            encoder_opts,
+254            format,
+255        )
+256
+257        return resp
+258
+259    def _vrod_bench(self, server):
+260        out = {}
+261        pth = "spec.json"
+262        start_t = time.time()
+263        with open(pth, "w") as outfile:
+264            spec, sources, filters = self._to_json_spec()
+265            outfile.write(json.dumps(spec))
+266
+267        sources = [
+268            {
+269                "name": s._name,
+270                "path": s._path,
+271                "stream": s._stream,
+272                "service": s._service.as_json() if s._service is not None else None,
+273            }
+274            for s in sources
+275        ]
+276        filters = {
+277            k: {
+278                "filter": v._func,
+279                "args": v._kwargs,
+280            }
+281            for k, v in filters.items()
+282        }
+283        arrays = []
+284        end_t = time.time()
+285        out["vrod_create_spec"] = end_t - start_t
+286
+287        start = time.time()
+288        resp = server._new(pth, sources, filters, arrays, self._fmt)
+289        end = time.time()
+290        out["vrod_register"] = end - start
+291
+292        stream_url = resp["stream_url"]
+293        first_segment = stream_url.replace("stream.m3u8", "segment-0.ts")
+294
+295        start = time.time()
+296        r = requests.get(first_segment)
+297        r.raise_for_status()
+298        end = time.time()
+299        out["vrod_first_segment"] = end - start
+300        return out
+301
+302    def _dve2_bench(self, server):
+303        pth = "spec.json"
+304        out = {}
+305        start_t = time.time()
+306        with open(pth, "w") as outfile:
+307            spec, sources, filters = self._to_json_spec()
+308            outfile.write(json.dumps(spec))
+309
+310        sources = [
+311            {
+312                "name": s._name,
+313                "path": s._path,
+314                "stream": s._stream,
+315                "service": s._service.as_json() if s._service is not None else None,
+316            }
+317            for s in sources
+318        ]
+319        filters = {
+320            k: {
+321                "filter": v._func,
+322                "args": v._kwargs,
+323            }
+324            for k, v in filters.items()
+325        }
+326        arrays = []
+327        end_t = time.time()
+328        out["dve2_create_spec"] = end_t - start_t
+329
+330        start = time.time()
+331        resp = server._export(pth, sources, filters, arrays, self._fmt, None, None)
+332        end = time.time()
+333        out["dve2_exec"] = end - start
+334        return out
+335
+336
+337class Loader:
+338    def __init__(self, server, namespace: str, domain):
+339        self._server = server
+340        self._namespace = namespace
+341        self._domain = domain
+342
+343    def _chunk(self, start_i, end_i):
+344        return self._server._raw(self._namespace, start_i, end_i)
+345
+346    def __len__(self):
+347        return len(self._domain)
+348
+349    def _find_index_by_rational(self, value):
+350        if value not in self._domain:
+351            raise ValueError(f"Rational timestamp {value} is not in the domain")
+352        return self._domain.index(value)
+353
+354    def __getitem__(self, index):
+355        if isinstance(index, slice):
+356            start = index.start if index.start is not None else 0
+357            end = index.stop if index.stop is not None else len(self._domain)
+358            assert start >= 0 and start < len(self._domain)
+359            assert end >= 0 and end <= len(self._domain)
+360            assert start <= end
+361            num_frames = end - start
+362            all_bytes = self._chunk(start, end - 1)
+363            all_bytes_len = len(all_bytes)
+364            assert all_bytes_len % num_frames == 0
+365            return [
+366                all_bytes[
+367                    i
+368                    * all_bytes_len
+369                    // num_frames : (i + 1)
+370                    * all_bytes_len
+371                    // num_frames
+372                ]
+373                for i in range(num_frames)
+374            ]
+375        elif isinstance(index, int):
+376            assert index >= 0 and index < len(self._domain)
+377            return self._chunk(index, index)
+378        else:
+379            raise TypeError(
+380                "Invalid argument type for iloc. Use a slice or an integer."
+381            )
+382
+383
+384class YrdenServer:
+385    """
+386    A connection to a Yrden server.
+387
+388    A yrden server is the main API for local use of vidformer.
+389    """
+390
+391    def __init__(self, domain=None, port=None, bin=None, hls_prefix=None):
+392        """
+393        Connect to a Yrden server
+394
+395        Can either connect to an existing server, if domain and port are provided, or start a new server using the provided binary.
+396        If no domain or binary is provided, the `VIDFORMER_BIN` environment variable is used.
+397        """
+398
+399        self._domain = domain
+400        self._port = port
+401        self._proc = None
+402        if self._port is None:
+403            if bin is None:
+404                if os.getenv("VIDFORMER_BIN") is not None:
+405                    bin = os.getenv("VIDFORMER_BIN")
+406                else:
+407                    bin = "vidformer-cli"
+408
+409            self._domain = "localhost"
+410            self._port = random.randint(49152, 65535)
+411            cmd = [bin, "yrden", "--port", str(self._port)]
+412            if _in_notebook:
+413                # We need to print the URL in the notebook
+414                # This is a trick to get VS Code to forward the port
+415                cmd += ["--print-url"]
+416
+417            if hls_prefix is not None:
+418                if not type(hls_prefix) == str:
+419                    raise Exception("hls_prefix must be a string")
+420                cmd += ["--hls-prefix", hls_prefix]
+421
+422            self._proc = subprocess.Popen(cmd)
+423
+424        version = _check_hls_link_exists(f"http://{self._domain}:{self._port}/")
+425        if version is None:
+426            raise Exception("Failed to connect to server")
+427
+428        expected_version = f"vidformer-yrden v{__version__}"
+429        if version != expected_version:
+430            print(
+431                f"Warning: Expected version `{expected_version}`, got `{version}`. API may not be compatible!"
+432            )
+433
+434    def _source(self, name: str, path: str, stream: int, service):
+435        r = requests.post(
+436            f"http://{self._domain}:{self._port}/source",
+437            json={
+438                "name": name,
+439                "path": path,
+440                "stream": stream,
+441                "service": service.as_json() if service is not None else None,
+442            },
+443        )
+444        if not r.ok:
+445            raise Exception(r.text)
+446
+447        resp = r.json()
+448        resp["ts"] = [Fraction(x[0], x[1]) for x in resp["ts"]]
+449        return resp
+450
+451    def _new(self, spec, sources, filters, arrays, fmt):
+452        req = {
+453            "spec": spec,
+454            "sources": sources,
+455            "filters": filters,
+456            "arrays": arrays,
+457            "width": fmt["width"],
+458            "height": fmt["height"],
+459            "pix_fmt": fmt["pix_fmt"],
+460        }
+461
+462        r = requests.post(f"http://{self._domain}:{self._port}/new", json=req)
+463        if not r.ok:
+464            raise Exception(r.text)
+465
+466        return r.json()
+467
+468    def _export(
+469        self, pth, spec, sources, filters, arrays, fmt, encoder, encoder_opts, format
+470    ):
+471        req = {
+472            "spec": spec,
+473            "sources": sources,
+474            "filters": filters,
+475            "arrays": arrays,
+476            "width": fmt["width"],
+477            "height": fmt["height"],
+478            "pix_fmt": fmt["pix_fmt"],
+479            "output_path": pth,
+480            "encoder": encoder,
+481            "encoder_opts": encoder_opts,
+482            "format": format,
+483        }
+484
+485        r = requests.post(f"http://{self._domain}:{self._port}/export", json=req)
+486        if not r.ok:
+487            raise Exception(r.text)
+488
+489        return r.json()
+490
+491    def _raw(self, namespace, start_i, end_i):
+492        r = requests.get(
+493            f"http://{self._domain}:{self._port}/{namespace}/raw/{start_i}-{end_i}"
+494        )
+495        if not r.ok:
+496            raise Exception(r.text)
+497        return r.content
+498
+499    def hls_js_url(self):
+500        """Return the link to the yrden-hosted hls.js file"""
+501        return f"http://{self._domain}:{self._port}/hls.js"
+502
+503    def __del__(self):
+504        if self._proc is not None:
+505            self._proc.kill()
+506
+507
+508class SourceExpr:
+509    def __init__(self, source, idx, is_iloc):
+510        self._source = source
+511        self._idx = idx
+512        self._is_iloc = is_iloc
+513
+514    def __repr__(self):
+515        if self._is_iloc:
+516            return f"{self._source._name}.iloc[{self._idx}]"
+517        else:
+518            return f"{self._source._name}[{self._idx}]"
+519
+520    def _to_json_spec(self):
+521        if self._is_iloc:
+522            return {
+523                "Source": {
+524                    "video": self._source._name,
+525                    "index": {"ILoc": int(self._idx)},
+526                }
+527            }
+528        else:
+529            return {
+530                "Source": {
+531                    "video": self._source._name,
+532                    "index": {"T": [self._idx.numerator, self._idx.denominator]},
+533                }
+534            }
+535
+536    def _sources(self):
+537        return set([self._source])
+538
+539    def _filters(self):
+540        return {}
+541
+542
+543class SourceILoc:
+544    def __init__(self, source):
+545        self._source = source
+546
+547    def __getitem__(self, idx):
+548        if type(idx) != int:
+549            raise Exception(f"Source iloc index must be an integer, got a {type(idx)}")
+550        return SourceExpr(self._source, idx, True)
+551
+552
+553class Source:
+554    """A video source."""
+555
+556    def __init__(
+557        self, server: YrdenServer, name: str, path: str, stream: int, service=None
+558    ):
+559        if service is None:
+560            # check if path is a http URL and, if so, automatically set the service
+561            # for example, the following code should work with just vf.Source(server, "tos_720p", "https://f.dominik.win/data/dve2/tos_720p.mp4")
+562            # this creates a storage service with endpoint "https://f.dominik.win/" and path "data/dve2/tos_720p.mp4"
+563            # don't use the root parameter in this case
+564
+565            match = re.match(r"(http|https)://([^/]+)(.*)", path)
+566            if match is not None:
+567                endpoint = f"{match.group(1)}://{match.group(2)}"
+568                path = match.group(3)
+569                # remove leading slash
+570                if path.startswith("/"):
+571                    path = path[1:]
+572                service = StorageService("http", endpoint=endpoint)
+573
+574        self._server = server
+575        self._name = name
+576        self._path = path
+577        self._stream = stream
+578        self._service = service
+579
+580        self.iloc = SourceILoc(self)
+581
+582        self._src = self._server._source(
+583            self._name, self._path, self._stream, self._service
+584        )
+585
+586    def fmt(self):
+587        return {
+588            "width": self._src["width"],
+589            "height": self._src["height"],
+590            "pix_fmt": self._src["pix_fmt"],
+591        }
+592
+593    def ts(self):
+594        return self._src["ts"]
+595
+596    def __len__(self):
+597        return len(self._src["ts"])
+598
+599    def __getitem__(self, idx):
+600        if type(idx) != Fraction:
+601            raise Exception("Source index must be a Fraction")
+602        return SourceExpr(self, idx, False)
+603
+604    def play(self, *args, **kwargs):
+605        """Play the video live in the notebook."""
+606
+607        domain = self.ts()
+608        render = lambda t, i: self[t]
+609        spec = Spec(domain, render, self.fmt())
+610        return spec.play(*args, **kwargs)
+611
+612
+613class StorageService:
+614    def __init__(self, service: str, **kwargs):
+615        if type(service) != str:
+616            raise Exception("Service name must be a string")
+617        self._service = service
+618        for k, v in kwargs.items():
+619            if type(v) != str:
+620                raise Exception(f"Value of {k} must be a string")
+621        self._config = kwargs
+622
+623    def as_json(self):
+624        return {"service": self._service, "config": self._config}
+625
+626    def __repr__(self):
+627        return f"{self._service}(config={self._config})"
+628
+629
+630def _json_arg(arg, skip_data_anot=False):
+631    if type(arg) == FilterExpr or type(arg) == SourceExpr:
+632        return {"Frame": arg._to_json_spec()}
+633    elif type(arg) == int:
+634        if skip_data_anot:
+635            return {"Int": arg}
+636        return {"Data": {"Int": arg}}
+637    elif type(arg) == str:
+638        if skip_data_anot:
+639            return {"String": arg}
+640        return {"Data": {"String": arg}}
+641    elif type(arg) == bytes:
+642        arg = list(arg)
+643        if skip_data_anot:
+644            return {"Bytes": arg}
+645        return {"Data": {"Bytes": arg}}
+646    elif type(arg) == float:
+647        if skip_data_anot:
+648            return {"Float": arg}
+649        return {"Data": {"Float": arg}}
+650    elif type(arg) == bool:
+651        if skip_data_anot:
+652            return {"Bool": arg}
+653        return {"Data": {"Bool": arg}}
+654    elif type(arg) == tuple or type(arg) == list:
+655        if skip_data_anot:
+656            return {"List": [_json_arg(x, True) for x in list(arg)]}
+657        return {"Data": {"List": [_json_arg(x, True) for x in list(arg)]}}
+658    else:
+659        raise Exception(f"Unknown arg type: {type(arg)}")
+660
+661
+662class Filter:
+663    """A video filter."""
+664
+665    def __init__(self, name: str, tl_func=None, **kwargs):
+666        self._name = name
+667
+668        # tl_func is the top level func, which is the true implementation, not just a pretty name
+669        if tl_func is None:
+670            self._func = name
+671        else:
+672            self._func = tl_func
+673
+674        # filter infra args, not invocation args
+675        for k, v in kwargs.items():
+676            if type(v) != str:
+677                raise Exception(f"Value of {k} must be a string")
+678        self._kwargs = kwargs
+679
+680    def __call__(self, *args, **kwargs):
+681        return FilterExpr(self, args, kwargs)
+682
+683
+684class FilterExpr:
+685    def __init__(self, filter: Filter, args, kwargs):
+686        self._filter = filter
+687        self._args = args
+688        self._kwargs = kwargs
+689
+690    def __repr__(self):
+691        args = []
+692        for arg in self._args:
+693            val = f'"{arg}"' if type(arg) == str else str(arg)
+694            args.append(str(val))
+695        for k, v in self._kwargs.items():
+696            val = f'"{v}"' if type(v) == str else str(v)
+697            args.append(f"{k}={val}")
+698        return f"{self._filter._name}({', '.join(args)})"
+699
+700    def _to_json_spec(self):
+701        args = []
+702        for arg in self._args:
+703            args.append(_json_arg(arg))
+704        kwargs = {}
+705        for k, v in self._kwargs.items():
+706            kwargs[k] = _json_arg(v)
+707        return {"Filter": {"name": self._filter._name, "args": args, "kwargs": kwargs}}
+708
+709    def _sources(self):
+710        s = set()
+711        for arg in self._args:
+712            if type(arg) == FilterExpr or type(arg) == SourceExpr:
+713                s = s.union(arg._sources())
+714        for arg in self._kwargs.values():
+715            if type(arg) == FilterExpr or type(arg) == SourceExpr:
+716                s = s.union(arg._sources())
+717        return s
+718
+719    def _filters(self):
+720        f = {self._filter._name: self._filter}
+721        for arg in self._args:
+722            if type(arg) == FilterExpr:
+723                f = {**f, **arg._filters()}
+724        for arg in self._kwargs.values():
+725            if type(arg) == FilterExpr:
+726                f = {**f, **arg._filters()}
+727        return f
+728
+729
+730class UDF:
+731    """User-defined filter superclass"""
+732
+733    def __init__(self, name: str):
+734        self._name = name
+735        self._socket_path = None
+736        self._p = None
+737
+738    def filter(self, *args, **kwargs):
+739        raise Exception("User must implement the filter method")
+740
+741    def filter_type(self, *args, **kwargs):
+742        raise Exception("User must implement the filter_type method")
+743
+744    def into_filter(self):
+745        assert self._socket_path is None
+746        self._socket_path = f"/tmp/vidformer-{self._name}-{str(uuid.uuid4())}.sock"
+747        self._p = multiprocessing.Process(
+748            target=_run_udf_host, args=(self, self._socket_path)
+749        )
+750        self._p.start()
+751        return Filter(
+752            name=self._name, tl_func="IPC", socket=self._socket_path, func=self._name
+753        )
+754
+755    def _handle_connection(self, connection):
+756        try:
+757            while True:
+758                frame_len = connection.recv(4)
+759                if not frame_len or len(frame_len) != 4:
+760                    break
+761                frame_len = int.from_bytes(frame_len, byteorder="big")
+762                data = connection.recv(frame_len)
+763                if not data:
+764                    break
+765
+766                while len(data) < frame_len:
+767                    new_data = connection.recv(frame_len - len(data))
+768                    if not new_data:
+769                        raise Exception("Partial data received")
+770                    data += new_data
+771
+772                obj = msgpack.unpackb(data, raw=False)
+773                f_func, f_op, f_args, f_kwargs = (
+774                    obj["func"],
+775                    obj["op"],
+776                    obj["args"],
+777                    obj["kwargs"],
+778                )
+779
+780                response = None
+781                if f_op == "filter":
+782                    f_args = [self._deser_filter(x) for x in f_args]
+783                    f_kwargs = {k: self._deser_filter(v) for k, v in f_kwargs}
+784                    response = self.filter(*f_args, **f_kwargs)
+785                    if type(response) != UDFFrame:
+786                        raise Exception(
+787                            f"filter must return a UDFFrame, got {type(response)}"
+788                        )
+789                    if response.frame_type().pix_fmt() != "rgb24":
+790                        raise Exception(
+791                            f"filter must return a frame with pix_fmt 'rgb24', got {response.frame_type().pix_fmt()}"
+792                        )
+793
+794                    response = response._response_ser()
+795                elif f_op == "filter_type":
+796                    f_args = [self._deser_filter_type(x) for x in f_args]
+797                    f_kwargs = {k: self._deser_filter_type(v) for k, v in f_kwargs}
+798                    response = self.filter_type(*f_args, **f_kwargs)
+799                    if type(response) != UDFFrameType:
+800                        raise Exception(
+801                            f"filter_type must return a UDFFrameType, got {type(response)}"
+802                        )
+803                    if response.pix_fmt() != "rgb24":
+804                        raise Exception(
+805                            f"filter_type must return a frame with pix_fmt 'rgb24', got {response.pix_fmt()}"
+806                        )
+807                    response = response._response_ser()
+808                else:
+809                    raise Exception(f"Unknown operation: {f_op}")
+810
+811                response = msgpack.packb(response, use_bin_type=True)
+812                response_len = len(response).to_bytes(4, byteorder="big")
+813                connection.sendall(response_len)
+814                connection.sendall(response)
+815        finally:
+816            connection.close()
+817
+818    def _deser_filter_type(self, obj):
+819        assert type(obj) == dict
+820        keys = list(obj.keys())
+821        assert len(keys) == 1
+822        type_key = keys[0]
+823        assert type_key in ["FrameType", "String", "Int", "Bool"]
+824
+825        if type_key == "FrameType":
+826            frame = obj[type_key]
+827            assert type(frame) == dict
+828            assert "width" in frame
+829            assert "height" in frame
+830            assert "format" in frame
+831            assert type(frame["width"]) == int
+832            assert type(frame["height"]) == int
+833            assert frame["format"] == 2  # AV_PIX_FMT_RGB24
+834            return UDFFrameType(frame["width"], frame["height"], "rgb24")
+835        elif type_key == "String":
+836            assert type(obj[type_key]) == str
+837            return obj[type_key]
+838        elif type_key == "Int":
+839            assert type(obj[type_key]) == int
+840            return obj[type_key]
+841        elif type_key == "Bool":
+842            assert type(obj[type_key]) == bool
+843            return obj[type_key]
+844        else:
+845            assert False, f"Unknown type: {type_key}"
+846
+847    def _deser_filter(self, obj):
+848        assert type(obj) == dict
+849        keys = list(obj.keys())
+850        assert len(keys) == 1
+851        type_key = keys[0]
+852        assert type_key in ["Frame", "String", "Int", "Bool"]
+853
+854        if type_key == "Frame":
+855            frame = obj[type_key]
+856            assert type(frame) == dict
+857            assert "data" in frame
+858            assert "width" in frame
+859            assert "height" in frame
+860            assert "format" in frame
+861            assert type(frame["width"]) == int
+862            assert type(frame["height"]) == int
+863            assert frame["format"] == "rgb24"
+864            assert type(frame["data"]) == bytes
+865
+866            data = np.frombuffer(frame["data"], dtype=np.uint8)
+867            data = data.reshape(frame["height"], frame["width"], 3)
+868            return UDFFrame(
+869                data, UDFFrameType(frame["width"], frame["height"], "rgb24")
+870            )
+871        elif type_key == "String":
+872            assert type(obj[type_key]) == str
+873            return obj[type_key]
+874        elif type_key == "Int":
+875            assert type(obj[type_key]) == int
+876            return obj[type_key]
+877        elif type_key == "Bool":
+878            assert type(obj[type_key]) == bool
+879            return obj[type_key]
+880        else:
+881            assert False, f"Unknown type: {type_key}"
+882
+883    def _host(self, socket_path: str):
+884        if os.path.exists(socket_path):
+885            os.remove(socket_path)
+886
+887        # start listening on the socket
+888        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+889        sock.bind(socket_path)
+890        sock.listen(1)
+891
+892        while True:
+893            # accept incoming connection
+894            connection, client_address = sock.accept()
+895            thread = threading.Thread(
+896                target=self._handle_connection, args=(connection,)
+897            )
+898            thread.start()
+899
+900    def __del__(self):
+901        if self._socket_path is not None:
+902            self._p.terminate()
+903            if os.path.exists(self._socket_path):
+904                # it's possible the process hasn't even created the socket yet
+905                os.remove(self._socket_path)
+906
+907
+908class UDFFrameType:
+909    """
+910    Frame type for use in UDFs.
+911    """
+912
+913    def __init__(self, width: int, height: int, pix_fmt: str):
+914        assert type(width) == int
+915        assert type(height) == int
+916        assert type(pix_fmt) == str
+917
+918        self._width = width
+919        self._height = height
+920        self._pix_fmt = pix_fmt
+921
+922    def width(self):
+923        return self._width
+924
+925    def height(self):
+926        return self._height
+927
+928    def pix_fmt(self):
+929        return self._pix_fmt
+930
+931    def _response_ser(self):
+932        return {
+933            "frame_type": {
+934                "width": self._width,
+935                "height": self._height,
+936                "format": 2,  # AV_PIX_FMT_RGB24
+937            }
+938        }
+939
+940    def __repr__(self):
+941        return f"FrameType<{self._width}x{self._height}, {self._pix_fmt}>"
+942
+943
+944class UDFFrame:
+945    """A symbolic reference to a frame for use in UDFs."""
+946
+947    def __init__(self, data: np.ndarray, f_type: UDFFrameType):
+948        assert type(data) == np.ndarray
+949        assert type(f_type) == UDFFrameType
+950
+951        # We only support RGB24 for now
+952        assert data.dtype == np.uint8
+953        assert data.shape[2] == 3
+954
+955        # check type matches
+956        assert data.shape[0] == f_type.height()
+957        assert data.shape[1] == f_type.width()
+958        assert f_type.pix_fmt() == "rgb24"
+959
+960        self._data = data
+961        self._f_type = f_type
+962
+963    def data(self):
+964        return self._data
+965
+966    def frame_type(self):
+967        return self._f_type
+968
+969    def _response_ser(self):
+970        return {
+971            "frame": {
+972                "data": self._data.tobytes(),
+973                "width": self._f_type.width(),
+974                "height": self._f_type.height(),
+975                "format": "rgb24",
+976            }
+977        }
+978
+979    def __repr__(self):
+980        return f"Frame<{self._f_type.width()}x{self._f_type.height()}, {self._f_type.pix_fmt()}>"
+981
+982
+983def _run_udf_host(udf: UDF, socket_path: str):
+984    udf._host(socket_path)
+
+ + +
+
+ +
+ + class + Spec: + + + +
+ +
 56class Spec:
+ 57    """
+ 58    A video transformation specification.
+ 59
+ 60    See https://ixlab.github.io/vidformer/concepts.html for more information.
+ 61    """
+ 62
+ 63    def __init__(self, domain: list[Fraction], render, fmt: dict):
+ 64        self._domain = domain
+ 65        self._render = render
+ 66        self._fmt = fmt
+ 67
+ 68    def __repr__(self):
+ 69        if len(self._domain) <= 20:
+ 70            lines = []
+ 71            for i, t in enumerate(self._domain):
+ 72                frame_expr = self._render(t, i)
+ 73                lines.append(
+ 74                    f"{t.numerator}/{t.denominator} => {frame_expr}",
+ 75                )
+ 76            return "\n".join(lines)
+ 77        else:
+ 78            lines = []
+ 79            for i, t in enumerate(self._domain[:10]):
+ 80                frame_expr = self._render(t, i)
+ 81                lines.append(
+ 82                    f"{t.numerator}/{t.denominator} => {frame_expr}",
+ 83                )
+ 84            lines.append("...")
+ 85            for i, t in enumerate(self._domain[-10:]):
+ 86                frame_expr = self._render(t, i)
+ 87                lines.append(
+ 88                    f"{t.numerator}/{t.denominator} => {frame_expr}",
+ 89                )
+ 90            return "\n".join(lines)
+ 91
+ 92    def _sources(self):
+ 93        s = set()
+ 94        for i, t in enumerate(self._domain):
+ 95            frame_expr = self._render(t, i)
+ 96            s = s.union(frame_expr._sources())
+ 97        return s
+ 98
+ 99    def _to_json_spec(self):
+100        frames = []
+101        s = set()
+102        f = {}
+103        for i, t in enumerate(self._domain):
+104            frame_expr = self._render(t, i)
+105            s = s.union(frame_expr._sources())
+106            f = {**f, **frame_expr._filters()}
+107            frame = [[t.numerator, t.denominator], frame_expr._to_json_spec()]
+108            frames.append(frame)
+109        return {"frames": frames}, s, f
+110
+111    def play(self, server, method="html", verbose=False):
+112        """Play the video live in the notebook."""
+113
+114        spec, sources, filters = self._to_json_spec()
+115        spec_json_bytes = json.dumps(spec).encode("utf-8")
+116        spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
+117        spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
+118
+119        sources = [
+120            {
+121                "name": s._name,
+122                "path": s._path,
+123                "stream": s._stream,
+124                "service": s._service.as_json() if s._service is not None else None,
+125            }
+126            for s in sources
+127        ]
+128        filters = {
+129            k: {
+130                "filter": v._func,
+131                "args": v._kwargs,
+132            }
+133            for k, v in filters.items()
+134        }
+135        arrays = []
+136
+137        if verbose:
+138            print(f"Sending to server. Spec is {len(spec_obj_json_gzip_b64)} bytes")
+139
+140        resp = server._new(spec_obj_json_gzip_b64, sources, filters, arrays, self._fmt)
+141        hls_video_url = resp["stream_url"]
+142        hls_player_url = resp["player_url"]
+143        namespace = resp["namespace"]
+144        hls_js_url = server.hls_js_url()
+145
+146        if method == "link":
+147            return hls_video_url
+148        if method == "player":
+149            return hls_player_url
+150        if method == "iframe":
+151            from IPython.display import IFrame
+152
+153            return IFrame(hls_player_url, width=1280, height=720)
+154        if method == "html":
+155            from IPython.display import HTML
+156
+157            # We add a namespace to the video element to avoid conflicts with other videos
+158            html_code = f"""
+159<!DOCTYPE html>
+160<html>
+161<head>
+162    <title>HLS Video Player</title>
+163    <!-- Include hls.js library -->
+164    <script src="{hls_js_url}"></script>
+165</head>
+166<body>
+167    <!-- Video element -->
+168    <video id="video-{namespace}" controls width="640" height="360" autoplay></video>
+169    <script>
+170        var video = document.getElementById('video-{namespace}');
+171        var videoSrc = '{hls_video_url}';
+172        var hls = new Hls();
+173        hls.loadSource(videoSrc);
+174        hls.attachMedia(video);
+175        hls.on(Hls.Events.MANIFEST_PARSED, function() {{
+176            video.play();
+177        }});
+178    </script>
+179</body>
+180</html>
+181"""
+182            return HTML(data=html_code)
+183        else:
+184            return hls_player_url
+185
+186    def load(self, server):
+187        spec, sources, filters = self._to_json_spec()
+188        spec_json_bytes = json.dumps(spec).encode("utf-8")
+189        spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
+190        spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
+191
+192        sources = [
+193            {
+194                "name": s._name,
+195                "path": s._path,
+196                "stream": s._stream,
+197                "service": s._service.as_json() if s._service is not None else None,
+198            }
+199            for s in sources
+200        ]
+201        filters = {
+202            k: {
+203                "filter": v._func,
+204                "args": v._kwargs,
+205            }
+206            for k, v in filters.items()
+207        }
+208        arrays = []
+209
+210        resp = server._new(spec_obj_json_gzip_b64, sources, filters, arrays, self._fmt)
+211        namespace = resp["namespace"]
+212        return Loader(server, namespace, self._domain)
+213
+214    def save(self, server, pth, encoder=None, encoder_opts=None, format=None):
+215        """Save the video to a file."""
+216
+217        assert encoder is None or type(encoder) == str
+218        assert encoder_opts is None or type(encoder_opts) == dict
+219        if encoder_opts is not None:
+220            for k, v in encoder_opts.items():
+221                assert type(k) == str and type(v) == str
+222
+223        spec, sources, filters = self._to_json_spec()
+224        spec_json_bytes = json.dumps(spec).encode("utf-8")
+225        spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
+226        spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
+227
+228        sources = [
+229            {
+230                "name": s._name,
+231                "path": s._path,
+232                "stream": s._stream,
+233                "service": s._service.as_json() if s._service is not None else None,
+234            }
+235            for s in sources
+236        ]
+237        filters = {
+238            k: {
+239                "filter": v._func,
+240                "args": v._kwargs,
+241            }
+242            for k, v in filters.items()
+243        }
+244        arrays = []
+245
+246        resp = server._export(
+247            pth,
+248            spec_obj_json_gzip_b64,
+249            sources,
+250            filters,
+251            arrays,
+252            self._fmt,
+253            encoder,
+254            encoder_opts,
+255            format,
+256        )
+257
+258        return resp
+259
+260    def _vrod_bench(self, server):
+261        out = {}
+262        pth = "spec.json"
+263        start_t = time.time()
+264        with open(pth, "w") as outfile:
+265            spec, sources, filters = self._to_json_spec()
+266            outfile.write(json.dumps(spec))
+267
+268        sources = [
+269            {
+270                "name": s._name,
+271                "path": s._path,
+272                "stream": s._stream,
+273                "service": s._service.as_json() if s._service is not None else None,
+274            }
+275            for s in sources
+276        ]
+277        filters = {
+278            k: {
+279                "filter": v._func,
+280                "args": v._kwargs,
+281            }
+282            for k, v in filters.items()
+283        }
+284        arrays = []
+285        end_t = time.time()
+286        out["vrod_create_spec"] = end_t - start_t
+287
+288        start = time.time()
+289        resp = server._new(pth, sources, filters, arrays, self._fmt)
+290        end = time.time()
+291        out["vrod_register"] = end - start
+292
+293        stream_url = resp["stream_url"]
+294        first_segment = stream_url.replace("stream.m3u8", "segment-0.ts")
+295
+296        start = time.time()
+297        r = requests.get(first_segment)
+298        r.raise_for_status()
+299        end = time.time()
+300        out["vrod_first_segment"] = end - start
+301        return out
+302
+303    def _dve2_bench(self, server):
+304        pth = "spec.json"
+305        out = {}
+306        start_t = time.time()
+307        with open(pth, "w") as outfile:
+308            spec, sources, filters = self._to_json_spec()
+309            outfile.write(json.dumps(spec))
+310
+311        sources = [
+312            {
+313                "name": s._name,
+314                "path": s._path,
+315                "stream": s._stream,
+316                "service": s._service.as_json() if s._service is not None else None,
+317            }
+318            for s in sources
+319        ]
+320        filters = {
+321            k: {
+322                "filter": v._func,
+323                "args": v._kwargs,
+324            }
+325            for k, v in filters.items()
+326        }
+327        arrays = []
+328        end_t = time.time()
+329        out["dve2_create_spec"] = end_t - start_t
+330
+331        start = time.time()
+332        resp = server._export(pth, sources, filters, arrays, self._fmt, None, None)
+333        end = time.time()
+334        out["dve2_exec"] = end - start
+335        return out
+
+ + +

A video transformation specification.

+ +

See https://ixlab.github.io/vidformer/concepts.html for more information.

+
+ + +
+ +
+ + Spec(domain: list[fractions.Fraction], render, fmt: dict) + + + +
+ +
63    def __init__(self, domain: list[Fraction], render, fmt: dict):
+64        self._domain = domain
+65        self._render = render
+66        self._fmt = fmt
+
+ + + + +
+
+ +
+ + def + play(self, server, method='html', verbose=False): + + + +
+ +
111    def play(self, server, method="html", verbose=False):
+112        """Play the video live in the notebook."""
+113
+114        spec, sources, filters = self._to_json_spec()
+115        spec_json_bytes = json.dumps(spec).encode("utf-8")
+116        spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
+117        spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
+118
+119        sources = [
+120            {
+121                "name": s._name,
+122                "path": s._path,
+123                "stream": s._stream,
+124                "service": s._service.as_json() if s._service is not None else None,
+125            }
+126            for s in sources
+127        ]
+128        filters = {
+129            k: {
+130                "filter": v._func,
+131                "args": v._kwargs,
+132            }
+133            for k, v in filters.items()
+134        }
+135        arrays = []
+136
+137        if verbose:
+138            print(f"Sending to server. Spec is {len(spec_obj_json_gzip_b64)} bytes")
+139
+140        resp = server._new(spec_obj_json_gzip_b64, sources, filters, arrays, self._fmt)
+141        hls_video_url = resp["stream_url"]
+142        hls_player_url = resp["player_url"]
+143        namespace = resp["namespace"]
+144        hls_js_url = server.hls_js_url()
+145
+146        if method == "link":
+147            return hls_video_url
+148        if method == "player":
+149            return hls_player_url
+150        if method == "iframe":
+151            from IPython.display import IFrame
+152
+153            return IFrame(hls_player_url, width=1280, height=720)
+154        if method == "html":
+155            from IPython.display import HTML
+156
+157            # We add a namespace to the video element to avoid conflicts with other videos
+158            html_code = f"""
+159<!DOCTYPE html>
+160<html>
+161<head>
+162    <title>HLS Video Player</title>
+163    <!-- Include hls.js library -->
+164    <script src="{hls_js_url}"></script>
+165</head>
+166<body>
+167    <!-- Video element -->
+168    <video id="video-{namespace}" controls width="640" height="360" autoplay></video>
+169    <script>
+170        var video = document.getElementById('video-{namespace}');
+171        var videoSrc = '{hls_video_url}';
+172        var hls = new Hls();
+173        hls.loadSource(videoSrc);
+174        hls.attachMedia(video);
+175        hls.on(Hls.Events.MANIFEST_PARSED, function() {{
+176            video.play();
+177        }});
+178    </script>
+179</body>
+180</html>
+181"""
+182            return HTML(data=html_code)
+183        else:
+184            return hls_player_url
+
+ + +

Play the video live in the notebook.

+
+ + +
+
+ +
+ + def + load(self, server): + + + +
+ +
186    def load(self, server):
+187        spec, sources, filters = self._to_json_spec()
+188        spec_json_bytes = json.dumps(spec).encode("utf-8")
+189        spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
+190        spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
+191
+192        sources = [
+193            {
+194                "name": s._name,
+195                "path": s._path,
+196                "stream": s._stream,
+197                "service": s._service.as_json() if s._service is not None else None,
+198            }
+199            for s in sources
+200        ]
+201        filters = {
+202            k: {
+203                "filter": v._func,
+204                "args": v._kwargs,
+205            }
+206            for k, v in filters.items()
+207        }
+208        arrays = []
+209
+210        resp = server._new(spec_obj_json_gzip_b64, sources, filters, arrays, self._fmt)
+211        namespace = resp["namespace"]
+212        return Loader(server, namespace, self._domain)
+
+ + + + +
+
+ +
+ + def + save(self, server, pth, encoder=None, encoder_opts=None, format=None): + + + +
+ +
214    def save(self, server, pth, encoder=None, encoder_opts=None, format=None):
+215        """Save the video to a file."""
+216
+217        assert encoder is None or type(encoder) == str
+218        assert encoder_opts is None or type(encoder_opts) == dict
+219        if encoder_opts is not None:
+220            for k, v in encoder_opts.items():
+221                assert type(k) == str and type(v) == str
+222
+223        spec, sources, filters = self._to_json_spec()
+224        spec_json_bytes = json.dumps(spec).encode("utf-8")
+225        spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
+226        spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
+227
+228        sources = [
+229            {
+230                "name": s._name,
+231                "path": s._path,
+232                "stream": s._stream,
+233                "service": s._service.as_json() if s._service is not None else None,
+234            }
+235            for s in sources
+236        ]
+237        filters = {
+238            k: {
+239                "filter": v._func,
+240                "args": v._kwargs,
+241            }
+242            for k, v in filters.items()
+243        }
+244        arrays = []
+245
+246        resp = server._export(
+247            pth,
+248            spec_obj_json_gzip_b64,
+249            sources,
+250            filters,
+251            arrays,
+252            self._fmt,
+253            encoder,
+254            encoder_opts,
+255            format,
+256        )
+257
+258        return resp
+
+ + +

Save the video to a file.

+
+ + +
+
+
+ +
+ + class + Loader: + + + +
+ +
338class Loader:
+339    def __init__(self, server, namespace: str, domain):
+340        self._server = server
+341        self._namespace = namespace
+342        self._domain = domain
+343
+344    def _chunk(self, start_i, end_i):
+345        return self._server._raw(self._namespace, start_i, end_i)
+346
+347    def __len__(self):
+348        return len(self._domain)
+349
+350    def _find_index_by_rational(self, value):
+351        if value not in self._domain:
+352            raise ValueError(f"Rational timestamp {value} is not in the domain")
+353        return self._domain.index(value)
+354
+355    def __getitem__(self, index):
+356        if isinstance(index, slice):
+357            start = index.start if index.start is not None else 0
+358            end = index.stop if index.stop is not None else len(self._domain)
+359            assert start >= 0 and start < len(self._domain)
+360            assert end >= 0 and end <= len(self._domain)
+361            assert start <= end
+362            num_frames = end - start
+363            all_bytes = self._chunk(start, end - 1)
+364            all_bytes_len = len(all_bytes)
+365            assert all_bytes_len % num_frames == 0
+366            return [
+367                all_bytes[
+368                    i
+369                    * all_bytes_len
+370                    // num_frames : (i + 1)
+371                    * all_bytes_len
+372                    // num_frames
+373                ]
+374                for i in range(num_frames)
+375            ]
+376        elif isinstance(index, int):
+377            assert index >= 0 and index < len(self._domain)
+378            return self._chunk(index, index)
+379        else:
+380            raise TypeError(
+381                "Invalid argument type for iloc. Use a slice or an integer."
+382            )
+
+ + + + +
+ +
+ + Loader(server, namespace: str, domain) + + + +
+ +
339    def __init__(self, server, namespace: str, domain):
+340        self._server = server
+341        self._namespace = namespace
+342        self._domain = domain
+
+ + + + +
+
+
+ +
+ + class + YrdenServer: + + + +
+ +
385class YrdenServer:
+386    """
+387    A connection to a Yrden server.
+388
+389    A yrden server is the main API for local use of vidformer.
+390    """
+391
+392    def __init__(self, domain=None, port=None, bin=None, hls_prefix=None):
+393        """
+394        Connect to a Yrden server
+395
+396        Can either connect to an existing server, if domain and port are provided, or start a new server using the provided binary.
+397        If no domain or binary is provided, the `VIDFORMER_BIN` environment variable is used.
+398        """
+399
+400        self._domain = domain
+401        self._port = port
+402        self._proc = None
+403        if self._port is None:
+404            if bin is None:
+405                if os.getenv("VIDFORMER_BIN") is not None:
+406                    bin = os.getenv("VIDFORMER_BIN")
+407                else:
+408                    bin = "vidformer-cli"
+409
+410            self._domain = "localhost"
+411            self._port = random.randint(49152, 65535)
+412            cmd = [bin, "yrden", "--port", str(self._port)]
+413            if _in_notebook:
+414                # We need to print the URL in the notebook
+415                # This is a trick to get VS Code to forward the port
+416                cmd += ["--print-url"]
+417
+418            if hls_prefix is not None:
+419                if not type(hls_prefix) == str:
+420                    raise Exception("hls_prefix must be a string")
+421                cmd += ["--hls-prefix", hls_prefix]
+422
+423            self._proc = subprocess.Popen(cmd)
+424
+425        version = _check_hls_link_exists(f"http://{self._domain}:{self._port}/")
+426        if version is None:
+427            raise Exception("Failed to connect to server")
+428
+429        expected_version = f"vidformer-yrden v{__version__}"
+430        if version != expected_version:
+431            print(
+432                f"Warning: Expected version `{expected_version}`, got `{version}`. API may not be compatible!"
+433            )
+434
+435    def _source(self, name: str, path: str, stream: int, service):
+436        r = requests.post(
+437            f"http://{self._domain}:{self._port}/source",
+438            json={
+439                "name": name,
+440                "path": path,
+441                "stream": stream,
+442                "service": service.as_json() if service is not None else None,
+443            },
+444        )
+445        if not r.ok:
+446            raise Exception(r.text)
+447
+448        resp = r.json()
+449        resp["ts"] = [Fraction(x[0], x[1]) for x in resp["ts"]]
+450        return resp
+451
+452    def _new(self, spec, sources, filters, arrays, fmt):
+453        req = {
+454            "spec": spec,
+455            "sources": sources,
+456            "filters": filters,
+457            "arrays": arrays,
+458            "width": fmt["width"],
+459            "height": fmt["height"],
+460            "pix_fmt": fmt["pix_fmt"],
+461        }
+462
+463        r = requests.post(f"http://{self._domain}:{self._port}/new", json=req)
+464        if not r.ok:
+465            raise Exception(r.text)
+466
+467        return r.json()
+468
+469    def _export(
+470        self, pth, spec, sources, filters, arrays, fmt, encoder, encoder_opts, format
+471    ):
+472        req = {
+473            "spec": spec,
+474            "sources": sources,
+475            "filters": filters,
+476            "arrays": arrays,
+477            "width": fmt["width"],
+478            "height": fmt["height"],
+479            "pix_fmt": fmt["pix_fmt"],
+480            "output_path": pth,
+481            "encoder": encoder,
+482            "encoder_opts": encoder_opts,
+483            "format": format,
+484        }
+485
+486        r = requests.post(f"http://{self._domain}:{self._port}/export", json=req)
+487        if not r.ok:
+488            raise Exception(r.text)
+489
+490        return r.json()
+491
+492    def _raw(self, namespace, start_i, end_i):
+493        r = requests.get(
+494            f"http://{self._domain}:{self._port}/{namespace}/raw/{start_i}-{end_i}"
+495        )
+496        if not r.ok:
+497            raise Exception(r.text)
+498        return r.content
+499
+500    def hls_js_url(self):
+501        """Return the link to the yrden-hosted hls.js file"""
+502        return f"http://{self._domain}:{self._port}/hls.js"
+503
+504    def __del__(self):
+505        if self._proc is not None:
+506            self._proc.kill()
+
+ + +

A connection to a Yrden server.

+ +

A yrden server is the main API for local use of vidformer.

+
+ + +
+ +
+ + YrdenServer(domain=None, port=None, bin=None, hls_prefix=None) + + + +
+ +
392    def __init__(self, domain=None, port=None, bin=None, hls_prefix=None):
+393        """
+394        Connect to a Yrden server
+395
+396        Can either connect to an existing server, if domain and port are provided, or start a new server using the provided binary.
+397        If no domain or binary is provided, the `VIDFORMER_BIN` environment variable is used.
+398        """
+399
+400        self._domain = domain
+401        self._port = port
+402        self._proc = None
+403        if self._port is None:
+404            if bin is None:
+405                if os.getenv("VIDFORMER_BIN") is not None:
+406                    bin = os.getenv("VIDFORMER_BIN")
+407                else:
+408                    bin = "vidformer-cli"
+409
+410            self._domain = "localhost"
+411            self._port = random.randint(49152, 65535)
+412            cmd = [bin, "yrden", "--port", str(self._port)]
+413            if _in_notebook:
+414                # We need to print the URL in the notebook
+415                # This is a trick to get VS Code to forward the port
+416                cmd += ["--print-url"]
+417
+418            if hls_prefix is not None:
+419                if not type(hls_prefix) == str:
+420                    raise Exception("hls_prefix must be a string")
+421                cmd += ["--hls-prefix", hls_prefix]
+422
+423            self._proc = subprocess.Popen(cmd)
+424
+425        version = _check_hls_link_exists(f"http://{self._domain}:{self._port}/")
+426        if version is None:
+427            raise Exception("Failed to connect to server")
+428
+429        expected_version = f"vidformer-yrden v{__version__}"
+430        if version != expected_version:
+431            print(
+432                f"Warning: Expected version `{expected_version}`, got `{version}`. API may not be compatible!"
+433            )
+
+ + +

Connect to a Yrden server

+ +

Can either connect to an existing server, if domain and port are provided, or start a new server using the provided binary. +If no domain or binary is provided, the VIDFORMER_BIN environment variable is used.

+
+ + +
+
+ +
+ + def + hls_js_url(self): + + + +
+ +
500    def hls_js_url(self):
+501        """Return the link to the yrden-hosted hls.js file"""
+502        return f"http://{self._domain}:{self._port}/hls.js"
+
+ + +

Return the link to the yrden-hosted hls.js file

+
+ + +
+
+
+ +
+ + class + SourceExpr: + + + +
+ +
509class SourceExpr:
+510    def __init__(self, source, idx, is_iloc):
+511        self._source = source
+512        self._idx = idx
+513        self._is_iloc = is_iloc
+514
+515    def __repr__(self):
+516        if self._is_iloc:
+517            return f"{self._source._name}.iloc[{self._idx}]"
+518        else:
+519            return f"{self._source._name}[{self._idx}]"
+520
+521    def _to_json_spec(self):
+522        if self._is_iloc:
+523            return {
+524                "Source": {
+525                    "video": self._source._name,
+526                    "index": {"ILoc": int(self._idx)},
+527                }
+528            }
+529        else:
+530            return {
+531                "Source": {
+532                    "video": self._source._name,
+533                    "index": {"T": [self._idx.numerator, self._idx.denominator]},
+534                }
+535            }
+536
+537    def _sources(self):
+538        return set([self._source])
+539
+540    def _filters(self):
+541        return {}
+
+ + + + +
+ +
+ + SourceExpr(source, idx, is_iloc) + + + +
+ +
510    def __init__(self, source, idx, is_iloc):
+511        self._source = source
+512        self._idx = idx
+513        self._is_iloc = is_iloc
+
+ + + + +
+
+
+ +
+ + class + SourceILoc: + + + +
+ +
544class SourceILoc:
+545    def __init__(self, source):
+546        self._source = source
+547
+548    def __getitem__(self, idx):
+549        if type(idx) != int:
+550            raise Exception(f"Source iloc index must be an integer, got a {type(idx)}")
+551        return SourceExpr(self._source, idx, True)
+
+ + + + +
+ +
+ + SourceILoc(source) + + + +
+ +
545    def __init__(self, source):
+546        self._source = source
+
+ + + + +
+
+
+ +
+ + class + Source: + + + +
+ +
554class Source:
+555    """A video source."""
+556
+557    def __init__(
+558        self, server: YrdenServer, name: str, path: str, stream: int, service=None
+559    ):
+560        if service is None:
+561            # check if path is a http URL and, if so, automatically set the service
+562            # for example, the following code should work with just vf.Source(server, "tos_720p", "https://f.dominik.win/data/dve2/tos_720p.mp4")
+563            # this creates a storage service with endpoint "https://f.dominik.win/" and path "data/dve2/tos_720p.mp4"
+564            # don't use the root parameter in this case
+565
+566            match = re.match(r"(http|https)://([^/]+)(.*)", path)
+567            if match is not None:
+568                endpoint = f"{match.group(1)}://{match.group(2)}"
+569                path = match.group(3)
+570                # remove leading slash
+571                if path.startswith("/"):
+572                    path = path[1:]
+573                service = StorageService("http", endpoint=endpoint)
+574
+575        self._server = server
+576        self._name = name
+577        self._path = path
+578        self._stream = stream
+579        self._service = service
+580
+581        self.iloc = SourceILoc(self)
+582
+583        self._src = self._server._source(
+584            self._name, self._path, self._stream, self._service
+585        )
+586
+587    def fmt(self):
+588        return {
+589            "width": self._src["width"],
+590            "height": self._src["height"],
+591            "pix_fmt": self._src["pix_fmt"],
+592        }
+593
+594    def ts(self):
+595        return self._src["ts"]
+596
+597    def __len__(self):
+598        return len(self._src["ts"])
+599
+600    def __getitem__(self, idx):
+601        if type(idx) != Fraction:
+602            raise Exception("Source index must be a Fraction")
+603        return SourceExpr(self, idx, False)
+604
+605    def play(self, *args, **kwargs):
+606        """Play the video live in the notebook."""
+607
+608        domain = self.ts()
+609        render = lambda t, i: self[t]
+610        spec = Spec(domain, render, self.fmt())
+611        return spec.play(*args, **kwargs)
+
+ + +

A video source.

+
+ + +
+ +
+ + Source( server: YrdenServer, name: str, path: str, stream: int, service=None) + + + +
+ +
557    def __init__(
+558        self, server: YrdenServer, name: str, path: str, stream: int, service=None
+559    ):
+560        if service is None:
+561            # check if path is a http URL and, if so, automatically set the service
+562            # for example, the following code should work with just vf.Source(server, "tos_720p", "https://f.dominik.win/data/dve2/tos_720p.mp4")
+563            # this creates a storage service with endpoint "https://f.dominik.win/" and path "data/dve2/tos_720p.mp4"
+564            # don't use the root parameter in this case
+565
+566            match = re.match(r"(http|https)://([^/]+)(.*)", path)
+567            if match is not None:
+568                endpoint = f"{match.group(1)}://{match.group(2)}"
+569                path = match.group(3)
+570                # remove leading slash
+571                if path.startswith("/"):
+572                    path = path[1:]
+573                service = StorageService("http", endpoint=endpoint)
+574
+575        self._server = server
+576        self._name = name
+577        self._path = path
+578        self._stream = stream
+579        self._service = service
+580
+581        self.iloc = SourceILoc(self)
+582
+583        self._src = self._server._source(
+584            self._name, self._path, self._stream, self._service
+585        )
+
+ + + + +
+
+
+ iloc + + +
+ + + + +
+
+ +
+ + def + fmt(self): + + + +
+ +
587    def fmt(self):
+588        return {
+589            "width": self._src["width"],
+590            "height": self._src["height"],
+591            "pix_fmt": self._src["pix_fmt"],
+592        }
+
+ + + + +
+
+ +
+ + def + ts(self): + + + +
+ +
594    def ts(self):
+595        return self._src["ts"]
+
+ + + + +
+
+ +
+ + def + play(self, *args, **kwargs): + + + +
+ +
605    def play(self, *args, **kwargs):
+606        """Play the video live in the notebook."""
+607
+608        domain = self.ts()
+609        render = lambda t, i: self[t]
+610        spec = Spec(domain, render, self.fmt())
+611        return spec.play(*args, **kwargs)
+
+ + +

Play the video live in the notebook.

+
+ + +
+
+
+ +
+ + class + StorageService: + + + +
+ +
614class StorageService:
+615    def __init__(self, service: str, **kwargs):
+616        if type(service) != str:
+617            raise Exception("Service name must be a string")
+618        self._service = service
+619        for k, v in kwargs.items():
+620            if type(v) != str:
+621                raise Exception(f"Value of {k} must be a string")
+622        self._config = kwargs
+623
+624    def as_json(self):
+625        return {"service": self._service, "config": self._config}
+626
+627    def __repr__(self):
+628        return f"{self._service}(config={self._config})"
+
+ + + + +
+ +
+ + StorageService(service: str, **kwargs) + + + +
+ +
615    def __init__(self, service: str, **kwargs):
+616        if type(service) != str:
+617            raise Exception("Service name must be a string")
+618        self._service = service
+619        for k, v in kwargs.items():
+620            if type(v) != str:
+621                raise Exception(f"Value of {k} must be a string")
+622        self._config = kwargs
+
+ + + + +
+
+ +
+ + def + as_json(self): + + + +
+ +
624    def as_json(self):
+625        return {"service": self._service, "config": self._config}
+
+ + + + +
+
+
+ +
+ + class + Filter: + + + +
+ +
663class Filter:
+664    """A video filter."""
+665
+666    def __init__(self, name: str, tl_func=None, **kwargs):
+667        self._name = name
+668
+669        # tl_func is the top level func, which is the true implementation, not just a pretty name
+670        if tl_func is None:
+671            self._func = name
+672        else:
+673            self._func = tl_func
+674
+675        # filter infra args, not invocation args
+676        for k, v in kwargs.items():
+677            if type(v) != str:
+678                raise Exception(f"Value of {k} must be a string")
+679        self._kwargs = kwargs
+680
+681    def __call__(self, *args, **kwargs):
+682        return FilterExpr(self, args, kwargs)
+
+ + +

A video filter.

+
+ + +
+ +
+ + Filter(name: str, tl_func=None, **kwargs) + + + +
+ +
666    def __init__(self, name: str, tl_func=None, **kwargs):
+667        self._name = name
+668
+669        # tl_func is the top level func, which is the true implementation, not just a pretty name
+670        if tl_func is None:
+671            self._func = name
+672        else:
+673            self._func = tl_func
+674
+675        # filter infra args, not invocation args
+676        for k, v in kwargs.items():
+677            if type(v) != str:
+678                raise Exception(f"Value of {k} must be a string")
+679        self._kwargs = kwargs
+
+ + + + +
+
+
+ +
+ + class + FilterExpr: + + + +
+ +
685class FilterExpr:
+686    def __init__(self, filter: Filter, args, kwargs):
+687        self._filter = filter
+688        self._args = args
+689        self._kwargs = kwargs
+690
+691    def __repr__(self):
+692        args = []
+693        for arg in self._args:
+694            val = f'"{arg}"' if type(arg) == str else str(arg)
+695            args.append(str(val))
+696        for k, v in self._kwargs.items():
+697            val = f'"{v}"' if type(v) == str else str(v)
+698            args.append(f"{k}={val}")
+699        return f"{self._filter._name}({', '.join(args)})"
+700
+701    def _to_json_spec(self):
+702        args = []
+703        for arg in self._args:
+704            args.append(_json_arg(arg))
+705        kwargs = {}
+706        for k, v in self._kwargs.items():
+707            kwargs[k] = _json_arg(v)
+708        return {"Filter": {"name": self._filter._name, "args": args, "kwargs": kwargs}}
+709
+710    def _sources(self):
+711        s = set()
+712        for arg in self._args:
+713            if type(arg) == FilterExpr or type(arg) == SourceExpr:
+714                s = s.union(arg._sources())
+715        for arg in self._kwargs.values():
+716            if type(arg) == FilterExpr or type(arg) == SourceExpr:
+717                s = s.union(arg._sources())
+718        return s
+719
+720    def _filters(self):
+721        f = {self._filter._name: self._filter}
+722        for arg in self._args:
+723            if type(arg) == FilterExpr:
+724                f = {**f, **arg._filters()}
+725        for arg in self._kwargs.values():
+726            if type(arg) == FilterExpr:
+727                f = {**f, **arg._filters()}
+728        return f
+
+ + + + +
+ +
+ + FilterExpr(filter: Filter, args, kwargs) + + + +
+ +
686    def __init__(self, filter: Filter, args, kwargs):
+687        self._filter = filter
+688        self._args = args
+689        self._kwargs = kwargs
+
+ + + + +
+
+
+ +
+ + class + UDF: + + + +
+ +
731class UDF:
+732    """User-defined filter superclass"""
+733
+734    def __init__(self, name: str):
+735        self._name = name
+736        self._socket_path = None
+737        self._p = None
+738
+739    def filter(self, *args, **kwargs):
+740        raise Exception("User must implement the filter method")
+741
+742    def filter_type(self, *args, **kwargs):
+743        raise Exception("User must implement the filter_type method")
+744
+745    def into_filter(self):
+746        assert self._socket_path is None
+747        self._socket_path = f"/tmp/vidformer-{self._name}-{str(uuid.uuid4())}.sock"
+748        self._p = multiprocessing.Process(
+749            target=_run_udf_host, args=(self, self._socket_path)
+750        )
+751        self._p.start()
+752        return Filter(
+753            name=self._name, tl_func="IPC", socket=self._socket_path, func=self._name
+754        )
+755
+756    def _handle_connection(self, connection):
+757        try:
+758            while True:
+759                frame_len = connection.recv(4)
+760                if not frame_len or len(frame_len) != 4:
+761                    break
+762                frame_len = int.from_bytes(frame_len, byteorder="big")
+763                data = connection.recv(frame_len)
+764                if not data:
+765                    break
+766
+767                while len(data) < frame_len:
+768                    new_data = connection.recv(frame_len - len(data))
+769                    if not new_data:
+770                        raise Exception("Partial data received")
+771                    data += new_data
+772
+773                obj = msgpack.unpackb(data, raw=False)
+774                f_func, f_op, f_args, f_kwargs = (
+775                    obj["func"],
+776                    obj["op"],
+777                    obj["args"],
+778                    obj["kwargs"],
+779                )
+780
+781                response = None
+782                if f_op == "filter":
+783                    f_args = [self._deser_filter(x) for x in f_args]
+784                    f_kwargs = {k: self._deser_filter(v) for k, v in f_kwargs}
+785                    response = self.filter(*f_args, **f_kwargs)
+786                    if type(response) != UDFFrame:
+787                        raise Exception(
+788                            f"filter must return a UDFFrame, got {type(response)}"
+789                        )
+790                    if response.frame_type().pix_fmt() != "rgb24":
+791                        raise Exception(
+792                            f"filter must return a frame with pix_fmt 'rgb24', got {response.frame_type().pix_fmt()}"
+793                        )
+794
+795                    response = response._response_ser()
+796                elif f_op == "filter_type":
+797                    f_args = [self._deser_filter_type(x) for x in f_args]
+798                    f_kwargs = {k: self._deser_filter_type(v) for k, v in f_kwargs}
+799                    response = self.filter_type(*f_args, **f_kwargs)
+800                    if type(response) != UDFFrameType:
+801                        raise Exception(
+802                            f"filter_type must return a UDFFrameType, got {type(response)}"
+803                        )
+804                    if response.pix_fmt() != "rgb24":
+805                        raise Exception(
+806                            f"filter_type must return a frame with pix_fmt 'rgb24', got {response.pix_fmt()}"
+807                        )
+808                    response = response._response_ser()
+809                else:
+810                    raise Exception(f"Unknown operation: {f_op}")
+811
+812                response = msgpack.packb(response, use_bin_type=True)
+813                response_len = len(response).to_bytes(4, byteorder="big")
+814                connection.sendall(response_len)
+815                connection.sendall(response)
+816        finally:
+817            connection.close()
+818
+819    def _deser_filter_type(self, obj):
+820        assert type(obj) == dict
+821        keys = list(obj.keys())
+822        assert len(keys) == 1
+823        type_key = keys[0]
+824        assert type_key in ["FrameType", "String", "Int", "Bool"]
+825
+826        if type_key == "FrameType":
+827            frame = obj[type_key]
+828            assert type(frame) == dict
+829            assert "width" in frame
+830            assert "height" in frame
+831            assert "format" in frame
+832            assert type(frame["width"]) == int
+833            assert type(frame["height"]) == int
+834            assert frame["format"] == 2  # AV_PIX_FMT_RGB24
+835            return UDFFrameType(frame["width"], frame["height"], "rgb24")
+836        elif type_key == "String":
+837            assert type(obj[type_key]) == str
+838            return obj[type_key]
+839        elif type_key == "Int":
+840            assert type(obj[type_key]) == int
+841            return obj[type_key]
+842        elif type_key == "Bool":
+843            assert type(obj[type_key]) == bool
+844            return obj[type_key]
+845        else:
+846            assert False, f"Unknown type: {type_key}"
+847
+848    def _deser_filter(self, obj):
+849        assert type(obj) == dict
+850        keys = list(obj.keys())
+851        assert len(keys) == 1
+852        type_key = keys[0]
+853        assert type_key in ["Frame", "String", "Int", "Bool"]
+854
+855        if type_key == "Frame":
+856            frame = obj[type_key]
+857            assert type(frame) == dict
+858            assert "data" in frame
+859            assert "width" in frame
+860            assert "height" in frame
+861            assert "format" in frame
+862            assert type(frame["width"]) == int
+863            assert type(frame["height"]) == int
+864            assert frame["format"] == "rgb24"
+865            assert type(frame["data"]) == bytes
+866
+867            data = np.frombuffer(frame["data"], dtype=np.uint8)
+868            data = data.reshape(frame["height"], frame["width"], 3)
+869            return UDFFrame(
+870                data, UDFFrameType(frame["width"], frame["height"], "rgb24")
+871            )
+872        elif type_key == "String":
+873            assert type(obj[type_key]) == str
+874            return obj[type_key]
+875        elif type_key == "Int":
+876            assert type(obj[type_key]) == int
+877            return obj[type_key]
+878        elif type_key == "Bool":
+879            assert type(obj[type_key]) == bool
+880            return obj[type_key]
+881        else:
+882            assert False, f"Unknown type: {type_key}"
+883
+884    def _host(self, socket_path: str):
+885        if os.path.exists(socket_path):
+886            os.remove(socket_path)
+887
+888        # start listening on the socket
+889        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+890        sock.bind(socket_path)
+891        sock.listen(1)
+892
+893        while True:
+894            # accept incoming connection
+895            connection, client_address = sock.accept()
+896            thread = threading.Thread(
+897                target=self._handle_connection, args=(connection,)
+898            )
+899            thread.start()
+900
+901    def __del__(self):
+902        if self._socket_path is not None:
+903            self._p.terminate()
+904            if os.path.exists(self._socket_path):
+905                # it's possible the process hasn't even created the socket yet
+906                os.remove(self._socket_path)
+
+ + +

User-defined filter superclass

+
+ + +
+ +
+ + UDF(name: str) + + + +
+ +
734    def __init__(self, name: str):
+735        self._name = name
+736        self._socket_path = None
+737        self._p = None
+
+ + + + +
+
+ +
+ + def + filter(self, *args, **kwargs): + + + +
+ +
739    def filter(self, *args, **kwargs):
+740        raise Exception("User must implement the filter method")
+
+ + + + +
+
+ +
+ + def + filter_type(self, *args, **kwargs): + + + +
+ +
742    def filter_type(self, *args, **kwargs):
+743        raise Exception("User must implement the filter_type method")
+
+ + + + +
+
+ +
+ + def + into_filter(self): + + + +
+ +
745    def into_filter(self):
+746        assert self._socket_path is None
+747        self._socket_path = f"/tmp/vidformer-{self._name}-{str(uuid.uuid4())}.sock"
+748        self._p = multiprocessing.Process(
+749            target=_run_udf_host, args=(self, self._socket_path)
+750        )
+751        self._p.start()
+752        return Filter(
+753            name=self._name, tl_func="IPC", socket=self._socket_path, func=self._name
+754        )
+
+ + + + +
+
+
+ +
+ + class + UDFFrameType: + + + +
+ +
909class UDFFrameType:
+910    """
+911    Frame type for use in UDFs.
+912    """
+913
+914    def __init__(self, width: int, height: int, pix_fmt: str):
+915        assert type(width) == int
+916        assert type(height) == int
+917        assert type(pix_fmt) == str
+918
+919        self._width = width
+920        self._height = height
+921        self._pix_fmt = pix_fmt
+922
+923    def width(self):
+924        return self._width
+925
+926    def height(self):
+927        return self._height
+928
+929    def pix_fmt(self):
+930        return self._pix_fmt
+931
+932    def _response_ser(self):
+933        return {
+934            "frame_type": {
+935                "width": self._width,
+936                "height": self._height,
+937                "format": 2,  # AV_PIX_FMT_RGB24
+938            }
+939        }
+940
+941    def __repr__(self):
+942        return f"FrameType<{self._width}x{self._height}, {self._pix_fmt}>"
+
+ + +

Frame type for use in UDFs.

+
+ + +
+ +
+ + UDFFrameType(width: int, height: int, pix_fmt: str) + + + +
+ +
914    def __init__(self, width: int, height: int, pix_fmt: str):
+915        assert type(width) == int
+916        assert type(height) == int
+917        assert type(pix_fmt) == str
+918
+919        self._width = width
+920        self._height = height
+921        self._pix_fmt = pix_fmt
+
+ + + + +
+
+ +
+ + def + width(self): + + + +
+ +
923    def width(self):
+924        return self._width
+
+ + + + +
+
+ +
+ + def + height(self): + + + +
+ +
926    def height(self):
+927        return self._height
+
+ + + + +
+
+ +
+ + def + pix_fmt(self): + + + +
+ +
929    def pix_fmt(self):
+930        return self._pix_fmt
+
+ + + + +
+
+
+ +
+ + class + UDFFrame: + + + +
+ +
945class UDFFrame:
+946    """A symbolic reference to a frame for use in UDFs."""
+947
+948    def __init__(self, data: np.ndarray, f_type: UDFFrameType):
+949        assert type(data) == np.ndarray
+950        assert type(f_type) == UDFFrameType
+951
+952        # We only support RGB24 for now
+953        assert data.dtype == np.uint8
+954        assert data.shape[2] == 3
+955
+956        # check type matches
+957        assert data.shape[0] == f_type.height()
+958        assert data.shape[1] == f_type.width()
+959        assert f_type.pix_fmt() == "rgb24"
+960
+961        self._data = data
+962        self._f_type = f_type
+963
+964    def data(self):
+965        return self._data
+966
+967    def frame_type(self):
+968        return self._f_type
+969
+970    def _response_ser(self):
+971        return {
+972            "frame": {
+973                "data": self._data.tobytes(),
+974                "width": self._f_type.width(),
+975                "height": self._f_type.height(),
+976                "format": "rgb24",
+977            }
+978        }
+979
+980    def __repr__(self):
+981        return f"Frame<{self._f_type.width()}x{self._f_type.height()}, {self._f_type.pix_fmt()}>"
+
+ + +

A symbolic reference to a frame for use in UDFs.

+
+ + +
+ +
+ + UDFFrame(data: numpy.ndarray, f_type: UDFFrameType) + + + +
+ +
948    def __init__(self, data: np.ndarray, f_type: UDFFrameType):
+949        assert type(data) == np.ndarray
+950        assert type(f_type) == UDFFrameType
+951
+952        # We only support RGB24 for now
+953        assert data.dtype == np.uint8
+954        assert data.shape[2] == 3
+955
+956        # check type matches
+957        assert data.shape[0] == f_type.height()
+958        assert data.shape[1] == f_type.width()
+959        assert f_type.pix_fmt() == "rgb24"
+960
+961        self._data = data
+962        self._f_type = f_type
+
+ + + + +
+
+ +
+ + def + data(self): + + + +
+ +
964    def data(self):
+965        return self._data
+
+ + + + +
+
+ +
+ + def + frame_type(self): + + + +
+ +
967    def frame_type(self):
+968        return self._f_type
+
+ + + + +
+
+
+ + \ No newline at end of file diff --git a/vidformer/all.html b/vidformer/all.html new file mode 100644 index 0000000..0165640 --- /dev/null +++ b/vidformer/all.html @@ -0,0 +1 @@ +List of all items in this crate
\ No newline at end of file diff --git a/vidformer/array/index.html b/vidformer/array/index.html new file mode 100644 index 0000000..1bd45b0 --- /dev/null +++ b/vidformer/array/index.html @@ -0,0 +1,5 @@ +vidformer::array - Rust
vidformer

Module array

source
Expand description

Arrays provide access to data.

+

Arrays store conventional data (e.g. numbers, strings) and can be referenced by specs. +As with the rest of the vidformer data model, arrays are duel-indexed by a timestamp or a position. +Arrays can be backed by a variety of sources, such as a JSON file or a database.

+

Structs§

Traits§

  • A trait for an array
\ No newline at end of file diff --git a/vidformer/array/sidebar-items.js b/vidformer/array/sidebar-items.js new file mode 100644 index 0000000..343e5a3 --- /dev/null +++ b/vidformer/array/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["JsonArary"],"trait":["Array"]}; \ No newline at end of file diff --git a/vidformer/array/struct.JsonArary.html b/vidformer/array/struct.JsonArary.html new file mode 100644 index 0000000..86e272f --- /dev/null +++ b/vidformer/array/struct.JsonArary.html @@ -0,0 +1,23 @@ +JsonArary in vidformer::array - Rust
vidformer::array

Struct JsonArary

source
pub struct JsonArary { /* private fields */ }
Expand description

An array backed by a JSON file

+

Trait Implementations§

source§

impl Array for JsonArary

source§

fn domain(&self) -> Vec<Rational64>

Returns the domain of the array. Read more
source§

fn index(&self, idx: usize) -> DataExpr

Returns the value at a given positional index.
source§

fn index_t(&self, idx: Rational64) -> DataExpr

Returns the value at a given time index.
source§

impl Debug for JsonArary

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for JsonArary

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Serialize for JsonArary

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/array/trait.Array.html b/vidformer/array/trait.Array.html new file mode 100644 index 0000000..ffd71a5 --- /dev/null +++ b/vidformer/array/trait.Array.html @@ -0,0 +1,18 @@ +Array in vidformer::array - Rust
vidformer::array

Trait Array

source
pub trait Array: Sync + Send {
+    // Required methods
+    fn domain(&self) -> Vec<Rational64>;
+    fn index(&self, idx: usize) -> DataExpr;
+    fn index_t(&self, idx: Rational64) -> DataExpr;
+}
Expand description

A trait for an array

+

Required Methods§

source

fn domain(&self) -> Vec<Rational64>

Returns the domain of the array.

+

The domain is the set of times at which the array is defined. +Each time corresponds to a single output value at that timestamp.

+

The output must:

+
    +
  • Be sorted in ascending order
  • +
  • Contain no duplicate values
  • +
  • Begin with 0
  • +
+
source

fn index(&self, idx: usize) -> DataExpr

Returns the value at a given positional index.

+
source

fn index_t(&self, idx: Rational64) -> DataExpr

Returns the value at a given time index.

+

Implementors§

\ No newline at end of file diff --git a/vidformer/dve/enum.Error.html b/vidformer/dve/enum.Error.html new file mode 100644 index 0000000..66e525c --- /dev/null +++ b/vidformer/dve/enum.Error.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/enum.Error.html...

+ + + \ No newline at end of file diff --git a/vidformer/dve/enum.RangeTsFormat.html b/vidformer/dve/enum.RangeTsFormat.html new file mode 100644 index 0000000..4a91491 --- /dev/null +++ b/vidformer/dve/enum.RangeTsFormat.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/enum.RangeTsFormat.html...

+ + + \ No newline at end of file diff --git a/vidformer/dve/fn.create_spec_hls.html b/vidformer/dve/fn.create_spec_hls.html new file mode 100644 index 0000000..b95240a --- /dev/null +++ b/vidformer/dve/fn.create_spec_hls.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/fn.create_spec_hls.html...

+ + + \ No newline at end of file diff --git a/vidformer/dve/fn.run.html b/vidformer/dve/fn.run.html new file mode 100644 index 0000000..a9d0161 --- /dev/null +++ b/vidformer/dve/fn.run.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/fn.run.html...

+ + + \ No newline at end of file diff --git a/vidformer/dve/fn.validate.html b/vidformer/dve/fn.validate.html new file mode 100644 index 0000000..19435e4 --- /dev/null +++ b/vidformer/dve/fn.validate.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/fn.validate.html...

+ + + \ No newline at end of file diff --git a/vidformer/dve/struct.Config.html b/vidformer/dve/struct.Config.html new file mode 100644 index 0000000..6e0d8c4 --- /dev/null +++ b/vidformer/dve/struct.Config.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/struct.Config.html...

+ + + \ No newline at end of file diff --git a/vidformer/dve/struct.Context.html b/vidformer/dve/struct.Context.html new file mode 100644 index 0000000..ac1c2d4 --- /dev/null +++ b/vidformer/dve/struct.Context.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/struct.Context.html...

+ + + \ No newline at end of file diff --git a/vidformer/dve/struct.EncoderConfig.html b/vidformer/dve/struct.EncoderConfig.html new file mode 100644 index 0000000..d242aec --- /dev/null +++ b/vidformer/dve/struct.EncoderConfig.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/struct.EncoderConfig.html...

+ + + \ No newline at end of file diff --git a/vidformer/dve/struct.Range.html b/vidformer/dve/struct.Range.html new file mode 100644 index 0000000..1a481e8 --- /dev/null +++ b/vidformer/dve/struct.Range.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/struct.Range.html...

+ + + \ No newline at end of file diff --git a/vidformer/dve/struct.Stats.html b/vidformer/dve/struct.Stats.html new file mode 100644 index 0000000..d48dc6a --- /dev/null +++ b/vidformer/dve/struct.Stats.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/struct.Stats.html...

+ + + \ No newline at end of file diff --git a/vidformer/enum.Error.html b/vidformer/enum.Error.html new file mode 100644 index 0000000..597fbfb --- /dev/null +++ b/vidformer/enum.Error.html @@ -0,0 +1,32 @@ +Error in vidformer - Rust
vidformer

Enum Error

source
pub enum Error {
+    SourceNotFound(String),
+    IndexOutOfBounds(String, IndexConst),
+    MissingFilterArg,
+    InvalidFilterArgType(String, String, String),
+    InvalidFilterArgValue(String, String),
+    FilterInternalError(String),
+    InvalidOutputFrameType,
+    ConfigError(String),
+    AVError(String),
+    IOError(String),
+    Unknown(String),
+}

Variants§

§

SourceNotFound(String)

§

IndexOutOfBounds(String, IndexConst)

§

MissingFilterArg

§

InvalidFilterArgType(String, String, String)

§

InvalidFilterArgValue(String, String)

§

FilterInternalError(String)

§

InvalidOutputFrameType

§

ConfigError(String)

§

AVError(String)

§

IOError(String)

§

Unknown(String)

Trait Implementations§

source§

impl Debug for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for Error

source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Error for Error

1.30.0 · source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more

Auto Trait Implementations§

§

impl Freeze for Error

§

impl RefUnwindSafe for Error

§

impl Send for Error

§

impl Sync for Error

§

impl Unpin for Error

§

impl UnwindSafe for Error

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/enum.RangeTsFormat.html b/vidformer/enum.RangeTsFormat.html new file mode 100644 index 0000000..e9f16c5 --- /dev/null +++ b/vidformer/enum.RangeTsFormat.html @@ -0,0 +1,29 @@ +RangeTsFormat in vidformer - Rust
vidformer

Enum RangeTsFormat

source
pub enum RangeTsFormat {
+    SegmentLocal,
+    StreamLocal,
+}
Expand description

Select whether the output timestamps are local to the ranged segment or the entire output

+
    +
  • SegmentLocal: The output timestamps are in the same timebase as the ranged segment. Used for VOD.
  • +
  • StreamLocal: The output timestamps are in the same timebase as the entire output.
  • +
+

Variants§

§

SegmentLocal

§

StreamLocal

Trait Implementations§

source§

impl Clone for RangeTsFormat

source§

fn clone(&self) -> RangeTsFormat

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/fn.filters.html b/vidformer/filter/builtin/fn.filters.html new file mode 100644 index 0000000..e0b6677 --- /dev/null +++ b/vidformer/filter/builtin/fn.filters.html @@ -0,0 +1,2 @@ +filters in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Function filters

source
pub fn filters() -> BTreeMap<String, Box<dyn Filter>>
Expand description

vidformer built-in filters

+
\ No newline at end of file diff --git a/vidformer/filter/builtin/index.html b/vidformer/filter/builtin/index.html new file mode 100644 index 0000000..258ce4a --- /dev/null +++ b/vidformer/filter/builtin/index.html @@ -0,0 +1,2 @@ +vidformer::filter::builtin - Rust
vidformer::filter

Module builtin

source
Expand description

vidformer built-in filters

+

Structs§

Functions§

\ No newline at end of file diff --git a/vidformer/filter/builtin/ipc/struct.IPC.html b/vidformer/filter/builtin/ipc/struct.IPC.html new file mode 100644 index 0000000..5d1e919 --- /dev/null +++ b/vidformer/filter/builtin/ipc/struct.IPC.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../../vidformer/filter/builtin/struct.IPC.html...

+ + + \ No newline at end of file diff --git a/vidformer/filter/builtin/sidebar-items.js b/vidformer/filter/builtin/sidebar-items.js new file mode 100644 index 0000000..e0a999c --- /dev/null +++ b/vidformer/filter/builtin/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["filters"],"struct":["Annotate","BoundingBox","BoundingBoxBound","Box","DrawBox","DrawText","HStack","IPC","InlineMat","Pad","PlaceholderFrame","Scale","SliceMat","SliceWriteMat","VStack"]}; \ No newline at end of file diff --git a/vidformer/filter/builtin/struct.Annotate.html b/vidformer/filter/builtin/struct.Annotate.html new file mode 100644 index 0000000..dc79202 --- /dev/null +++ b/vidformer/filter/builtin/struct.Annotate.html @@ -0,0 +1,27 @@ +Annotate in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct Annotate

source
pub struct Annotate {}

Trait Implementations§

source§

impl Filter for Annotate

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + _args: &[Val], + _kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.BoundingBox.html b/vidformer/filter/builtin/struct.BoundingBox.html new file mode 100644 index 0000000..b084c5c --- /dev/null +++ b/vidformer/filter/builtin/struct.BoundingBox.html @@ -0,0 +1,27 @@ +BoundingBox in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct BoundingBox

source
pub struct BoundingBox {}

Trait Implementations§

source§

impl Filter for BoundingBox

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + _kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.BoundingBoxBound.html b/vidformer/filter/builtin/struct.BoundingBoxBound.html new file mode 100644 index 0000000..66e7652 --- /dev/null +++ b/vidformer/filter/builtin/struct.BoundingBoxBound.html @@ -0,0 +1,21 @@ +BoundingBoxBound in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct BoundingBoxBound

source
pub struct BoundingBoxBound { /* private fields */ }

Trait Implementations§

source§

impl Debug for BoundingBoxBound

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for BoundingBoxBound

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.Box.html b/vidformer/filter/builtin/struct.Box.html new file mode 100644 index 0000000..17b6a83 --- /dev/null +++ b/vidformer/filter/builtin/struct.Box.html @@ -0,0 +1,27 @@ +Box in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct Box

source
pub struct Box {}

Trait Implementations§

source§

impl Filter for Box

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + _kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

§

impl Freeze for Box

§

impl RefUnwindSafe for Box

§

impl Send for Box

§

impl Sync for Box

§

impl Unpin for Box

§

impl UnwindSafe for Box

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.DrawBox.html b/vidformer/filter/builtin/struct.DrawBox.html new file mode 100644 index 0000000..1d0a7d3 --- /dev/null +++ b/vidformer/filter/builtin/struct.DrawBox.html @@ -0,0 +1,27 @@ +DrawBox in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct DrawBox

source
pub struct DrawBox {}

Trait Implementations§

source§

impl Filter for DrawBox

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + _kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.DrawText.html b/vidformer/filter/builtin/struct.DrawText.html new file mode 100644 index 0000000..cc2ee27 --- /dev/null +++ b/vidformer/filter/builtin/struct.DrawText.html @@ -0,0 +1,27 @@ +DrawText in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct DrawText

source
pub struct DrawText {}

Trait Implementations§

source§

impl Filter for DrawText

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + _kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.HStack.html b/vidformer/filter/builtin/struct.HStack.html new file mode 100644 index 0000000..d5ac6b1 --- /dev/null +++ b/vidformer/filter/builtin/struct.HStack.html @@ -0,0 +1,27 @@ +HStack in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct HStack

source
pub struct HStack {}

Trait Implementations§

source§

impl Filter for HStack

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

§

impl Freeze for HStack

§

impl RefUnwindSafe for HStack

§

impl Send for HStack

§

impl Sync for HStack

§

impl Unpin for HStack

§

impl UnwindSafe for HStack

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.IPC.html b/vidformer/filter/builtin/struct.IPC.html new file mode 100644 index 0000000..3014343 --- /dev/null +++ b/vidformer/filter/builtin/struct.IPC.html @@ -0,0 +1,30 @@ +IPC in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct IPC

source
pub struct IPC { /* private fields */ }
Expand description

Filter over IPC Socket

+

This filter sends requests to a filter server over a Unix socket. +TODO: Wire protocol documentation

+

Implementations§

source§

impl IPC

source

pub fn new(socket: String, func: String) -> Result<Self, Error>

source

pub fn via_map(config: &BTreeMap<String, String>) -> Result<Self, Error>

Trait Implementations§

source§

impl Filter for IPC

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

§

impl !Freeze for IPC

§

impl !RefUnwindSafe for IPC

§

impl Send for IPC

§

impl Sync for IPC

§

impl Unpin for IPC

§

impl UnwindSafe for IPC

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.InlineMat.html b/vidformer/filter/builtin/struct.InlineMat.html new file mode 100644 index 0000000..ec444cb --- /dev/null +++ b/vidformer/filter/builtin/struct.InlineMat.html @@ -0,0 +1,27 @@ +InlineMat in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct InlineMat

source
pub struct InlineMat;

Trait Implementations§

source§

impl Filter for InlineMat

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.Pad.html b/vidformer/filter/builtin/struct.Pad.html new file mode 100644 index 0000000..9be9eff --- /dev/null +++ b/vidformer/filter/builtin/struct.Pad.html @@ -0,0 +1,27 @@ +Pad in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct Pad

source
pub struct Pad {}

Trait Implementations§

source§

impl Filter for Pad

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

§

impl Freeze for Pad

§

impl RefUnwindSafe for Pad

§

impl Send for Pad

§

impl Sync for Pad

§

impl Unpin for Pad

§

impl UnwindSafe for Pad

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.PlaceholderFrame.html b/vidformer/filter/builtin/struct.PlaceholderFrame.html new file mode 100644 index 0000000..f66bfb2 --- /dev/null +++ b/vidformer/filter/builtin/struct.PlaceholderFrame.html @@ -0,0 +1,27 @@ +PlaceholderFrame in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct PlaceholderFrame

source
pub struct PlaceholderFrame {}

Trait Implementations§

source§

impl Filter for PlaceholderFrame

source§

fn filter( + &self, + _args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + _args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.Scale.html b/vidformer/filter/builtin/struct.Scale.html new file mode 100644 index 0000000..bb56f2a --- /dev/null +++ b/vidformer/filter/builtin/struct.Scale.html @@ -0,0 +1,34 @@ +Scale in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct Scale

source
pub struct Scale {}
Expand description

Scale & convert pixel format of a frame

+

§Arguments

+
    +
  • width - Width of the output frame (optional, but required if height is provided)
  • +
  • height - Height of the output frame (optional, but required if width is provided)
  • +
  • format - Pixel format of the output frame (optional)
  • +
+

Trait Implementations§

source§

impl Filter for Scale

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

§

impl Freeze for Scale

§

impl RefUnwindSafe for Scale

§

impl Send for Scale

§

impl Sync for Scale

§

impl Unpin for Scale

§

impl UnwindSafe for Scale

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.SliceMat.html b/vidformer/filter/builtin/struct.SliceMat.html new file mode 100644 index 0000000..524a24c --- /dev/null +++ b/vidformer/filter/builtin/struct.SliceMat.html @@ -0,0 +1,27 @@ +SliceMat in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct SliceMat

source
pub struct SliceMat {}

Trait Implementations§

source§

impl Filter for SliceMat

source§

fn filter( + &self, + args: &[Val], + _kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.SliceWriteMat.html b/vidformer/filter/builtin/struct.SliceWriteMat.html new file mode 100644 index 0000000..edca705 --- /dev/null +++ b/vidformer/filter/builtin/struct.SliceWriteMat.html @@ -0,0 +1,27 @@ +SliceWriteMat in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct SliceWriteMat

source
pub struct SliceWriteMat {}

Trait Implementations§

source§

impl Filter for SliceWriteMat

source§

fn filter( + &self, + args: &[Val], + _kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/builtin/struct.VStack.html b/vidformer/filter/builtin/struct.VStack.html new file mode 100644 index 0000000..fdb624d --- /dev/null +++ b/vidformer/filter/builtin/struct.VStack.html @@ -0,0 +1,27 @@ +VStack in vidformer::filter::builtin - Rust
vidformer::filter::builtin

Struct VStack

source
pub struct VStack {}

Trait Implementations§

source§

impl Filter for VStack

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

§

impl Freeze for VStack

§

impl RefUnwindSafe for VStack

§

impl Send for VStack

§

impl Sync for VStack

§

impl Unpin for VStack

§

impl UnwindSafe for VStack

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/cv2/fn.filters.html b/vidformer/filter/cv2/fn.filters.html new file mode 100644 index 0000000..3b697cc --- /dev/null +++ b/vidformer/filter/cv2/fn.filters.html @@ -0,0 +1,2 @@ +filters in vidformer::filter::cv2 - Rust
vidformer::filter::cv2

Function filters

source
pub fn filters() -> BTreeMap<String, Box<dyn Filter>>
Expand description

vidformer cv2 filters

+
\ No newline at end of file diff --git a/vidformer/filter/cv2/index.html b/vidformer/filter/cv2/index.html new file mode 100644 index 0000000..0c72ecf --- /dev/null +++ b/vidformer/filter/cv2/index.html @@ -0,0 +1,2 @@ +vidformer::filter::cv2 - Rust
vidformer::filter

Module cv2

source
Expand description

vidformer cv2 filters

+

Structs§

Functions§

\ No newline at end of file diff --git a/vidformer/filter/cv2/sidebar-items.js b/vidformer/filter/cv2/sidebar-items.js new file mode 100644 index 0000000..2ee82e4 --- /dev/null +++ b/vidformer/filter/cv2/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["filters"],"struct":["AddWeighted","ArrowedLine","Circle","Line","PutText","Rectangle","SetTo"]}; \ No newline at end of file diff --git a/vidformer/filter/cv2/struct.AddWeighted.html b/vidformer/filter/cv2/struct.AddWeighted.html new file mode 100644 index 0000000..656fcb9 --- /dev/null +++ b/vidformer/filter/cv2/struct.AddWeighted.html @@ -0,0 +1,27 @@ +AddWeighted in vidformer::filter::cv2 - Rust
vidformer::filter::cv2

Struct AddWeighted

source
pub struct AddWeighted {}

Trait Implementations§

source§

impl Filter for AddWeighted

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/cv2/struct.ArrowedLine.html b/vidformer/filter/cv2/struct.ArrowedLine.html new file mode 100644 index 0000000..ea5e3a8 --- /dev/null +++ b/vidformer/filter/cv2/struct.ArrowedLine.html @@ -0,0 +1,27 @@ +ArrowedLine in vidformer::filter::cv2 - Rust
vidformer::filter::cv2

Struct ArrowedLine

source
pub struct ArrowedLine {}

Trait Implementations§

source§

impl Filter for ArrowedLine

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/cv2/struct.Circle.html b/vidformer/filter/cv2/struct.Circle.html new file mode 100644 index 0000000..fe6af5c --- /dev/null +++ b/vidformer/filter/cv2/struct.Circle.html @@ -0,0 +1,27 @@ +Circle in vidformer::filter::cv2 - Rust
vidformer::filter::cv2

Struct Circle

source
pub struct Circle {}

Trait Implementations§

source§

impl Filter for Circle

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

§

impl Freeze for Circle

§

impl RefUnwindSafe for Circle

§

impl Send for Circle

§

impl Sync for Circle

§

impl Unpin for Circle

§

impl UnwindSafe for Circle

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/cv2/struct.Line.html b/vidformer/filter/cv2/struct.Line.html new file mode 100644 index 0000000..d063324 --- /dev/null +++ b/vidformer/filter/cv2/struct.Line.html @@ -0,0 +1,27 @@ +Line in vidformer::filter::cv2 - Rust
vidformer::filter::cv2

Struct Line

source
pub struct Line {}

Trait Implementations§

source§

impl Filter for Line

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

§

impl Freeze for Line

§

impl RefUnwindSafe for Line

§

impl Send for Line

§

impl Sync for Line

§

impl Unpin for Line

§

impl UnwindSafe for Line

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/cv2/struct.PutText.html b/vidformer/filter/cv2/struct.PutText.html new file mode 100644 index 0000000..cba5155 --- /dev/null +++ b/vidformer/filter/cv2/struct.PutText.html @@ -0,0 +1,27 @@ +PutText in vidformer::filter::cv2 - Rust
vidformer::filter::cv2

Struct PutText

source
pub struct PutText {}

Trait Implementations§

source§

impl Filter for PutText

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/cv2/struct.Rectangle.html b/vidformer/filter/cv2/struct.Rectangle.html new file mode 100644 index 0000000..2a4cd9e --- /dev/null +++ b/vidformer/filter/cv2/struct.Rectangle.html @@ -0,0 +1,27 @@ +Rectangle in vidformer::filter::cv2 - Rust
vidformer::filter::cv2

Struct Rectangle

source
pub struct Rectangle {}

Trait Implementations§

source§

impl Filter for Rectangle

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/cv2/struct.SetTo.html b/vidformer/filter/cv2/struct.SetTo.html new file mode 100644 index 0000000..e2ab36f --- /dev/null +++ b/vidformer/filter/cv2/struct.SetTo.html @@ -0,0 +1,27 @@ +SetTo in vidformer::filter::cv2 - Rust
vidformer::filter::cv2

Struct SetTo

source
pub struct SetTo {}

Trait Implementations§

source§

impl Filter for SetTo

source§

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs Read more
source§

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Auto Trait Implementations§

§

impl Freeze for SetTo

§

impl RefUnwindSafe for SetTo

§

impl Send for SetTo

§

impl Sync for SetTo

§

impl Unpin for SetTo

§

impl UnwindSafe for SetTo

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/enum.Val.html b/vidformer/filter/enum.Val.html new file mode 100644 index 0000000..34f4e13 --- /dev/null +++ b/vidformer/filter/enum.Val.html @@ -0,0 +1,33 @@ +Val in vidformer::filter - Rust
vidformer::filter

Enum Val

source
pub enum Val {
+    Frame(Frame),
+    FrameType(FrameType),
+    Bool(bool),
+    Int(i64),
+    String(String),
+    Bytes(Vec<u8>),
+    Float(f64),
+    List(Vec<Val>),
+}
Expand description

A value that can be passed to a filter

+

This can be a either a video frame or a conventional data value

+

Variants§

§

Frame(Frame)

§

FrameType(FrameType)

§

Bool(bool)

§

Int(i64)

§

String(String)

§

Bytes(Vec<u8>)

§

Float(f64)

§

List(Vec<Val>)

Implementations§

source§

impl Val

source

pub fn from_expr(expr: &DataExpr, context: &Context) -> Self

Trait Implementations§

source§

impl Clone for Val

source§

fn clone(&self) -> Val

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Val

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Serialize for Val

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl Freeze for Val

§

impl RefUnwindSafe for Val

§

impl Send for Val

§

impl Sync for Val

§

impl Unpin for Val

§

impl UnwindSafe for Val

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/index.html b/vidformer/filter/index.html new file mode 100644 index 0000000..9d7235c --- /dev/null +++ b/vidformer/filter/index.html @@ -0,0 +1,4 @@ +vidformer::filter - Rust
vidformer

Module filter

source
Expand description

Filters create and transform video frames

+

A filter is a function that takes some inputs and returns a video frame. +For example a filter could blur an input: MyBlur(frame, amount=5).

+

Modules§

  • vidformer built-in filters
  • vidformer cv2 filters

Structs§

Enums§

  • A value that can be passed to a filter

Traits§

  • A filter that can create a video frame from some inputs
\ No newline at end of file diff --git a/vidformer/filter/sidebar-items.js b/vidformer/filter/sidebar-items.js new file mode 100644 index 0000000..8590987 --- /dev/null +++ b/vidformer/filter/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["Val"],"mod":["builtin","cv2"],"struct":["Frame","FrameType"],"trait":["Filter"]}; \ No newline at end of file diff --git a/vidformer/filter/struct.Frame.html b/vidformer/filter/struct.Frame.html new file mode 100644 index 0000000..4898bde --- /dev/null +++ b/vidformer/filter/struct.Frame.html @@ -0,0 +1,28 @@ +Frame in vidformer::filter - Rust
vidformer::filter

Struct Frame

source
pub struct Frame {
+    pub width: i32,
+    pub height: i32,
+    pub format: AVPixelFormat,
+    /* private fields */
+}
Expand description

A decoded video frame

+

Fields§

§width: i32§height: i32§format: AVPixelFormat

Trait Implementations§

source§

impl Clone for Frame

source§

fn clone(&self) -> Frame

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Frame

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Frame

source§

fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>

Deserialize this value from the given Serde deserializer. Read more
source§

impl Serialize for Frame

source§

fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl Freeze for Frame

§

impl RefUnwindSafe for Frame

§

impl Send for Frame

§

impl Sync for Frame

§

impl Unpin for Frame

§

impl UnwindSafe for Frame

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/struct.FrameType.html b/vidformer/filter/struct.FrameType.html new file mode 100644 index 0000000..e4cad86 --- /dev/null +++ b/vidformer/filter/struct.FrameType.html @@ -0,0 +1,29 @@ +FrameType in vidformer::filter - Rust
vidformer::filter

Struct FrameType

source
pub struct FrameType {
+    pub width: usize,
+    pub height: usize,
+    pub format: AVPixelFormat,
+}

Fields§

§width: usize§height: usize§format: AVPixelFormat

Implementations§

source§

impl FrameType

source

pub fn new(width: usize, height: usize, format: AVPixelFormat) -> Self

Trait Implementations§

source§

impl Clone for FrameType

source§

fn clone(&self) -> FrameType

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for FrameType

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for FrameType

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl PartialEq for FrameType

source§

fn eq(&self, other: &FrameType) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
source§

impl Serialize for FrameType

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl Eq for FrameType

source§

impl StructuralPartialEq for FrameType

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/filter/trait.Filter.html b/vidformer/filter/trait.Filter.html new file mode 100644 index 0000000..9274fab --- /dev/null +++ b/vidformer/filter/trait.Filter.html @@ -0,0 +1,25 @@ +Filter in vidformer::filter - Rust
vidformer::filter

Trait Filter

source
pub trait Filter: Send + Sync {
+    // Required methods
+    fn filter(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<Frame, Error>;
+    fn filter_type(
+        &self,
+        args: &[Val],
+        kwargs: &BTreeMap<String, Val>,
+    ) -> Result<FrameType, Error>;
+}
Expand description

A filter that can create a video frame from some inputs

+

Required Methods§

source

fn filter( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<Frame, Error>

Creates a video frame from some inputs

+

The inputs are arbitrary and user provided. An input can either be +ordered (arg) or named (kwargs). This is similar to Python function calls.

+
source

fn filter_type( + &self, + args: &[Val], + kwargs: &BTreeMap<String, Val>, +) -> Result<FrameType, Error>

Implementors§

\ No newline at end of file diff --git a/vidformer/fn.codecs.html b/vidformer/fn.codecs.html new file mode 100644 index 0000000..191e95c --- /dev/null +++ b/vidformer/fn.codecs.html @@ -0,0 +1,2 @@ +codecs in vidformer - Rust
vidformer

Function codecs

source
pub fn codecs() -> Vec<CodecDescriptor>
Expand description

List all available codecs

+
\ No newline at end of file diff --git a/vidformer/fn.create_spec_hls.html b/vidformer/fn.create_spec_hls.html new file mode 100644 index 0000000..080c4b6 --- /dev/null +++ b/vidformer/fn.create_spec_hls.html @@ -0,0 +1,20 @@ +create_spec_hls in vidformer - Rust
vidformer

Function create_spec_hls

source
pub fn create_spec_hls(
+    spec: &dyn Spec,
+    host_prefix: &str,
+    context: &Context,
+    _config: &Config,
+) -> (String, String, String, Vec<(Rational64, Rational64)>)
Expand description

Create HLS artifacts for a spec

+
    +
  • spec - The spec to create HLS artifacts for
  • +
  • host_prefix - The prefix to use for the host (e.g., https://example.com:8000)
  • +
  • context - The context to use for the spec
  • +
  • config - The config to use for the spec
  • +
+

Returns a tuple of:

+
    +
  • The namespace for the HLS artifacts
  • +
  • The text of the m3u8 playlist file
  • +
  • The text of the m3u8 stream file
  • +
  • A vector of tuples of the start and end timestamps of each segment
  • +
+
\ No newline at end of file diff --git a/vidformer/fn.init.html b/vidformer/fn.init.html new file mode 100644 index 0000000..dbd9104 --- /dev/null +++ b/vidformer/fn.init.html @@ -0,0 +1,2 @@ +init in vidformer - Rust
vidformer

Function init

source
pub fn init()
Expand description

Instantiate FFmpeg logging

+
\ No newline at end of file diff --git a/vidformer/fn.run.html b/vidformer/fn.run.html new file mode 100644 index 0000000..976275f --- /dev/null +++ b/vidformer/fn.run.html @@ -0,0 +1,8 @@ +run in vidformer - Rust
vidformer

Function run

source
pub fn run(
+    spec: &Arc<Box<dyn Spec>>,
+    output_path: &str,
+    context: &Arc<Context>,
+    config: &Arc<Config>,
+    range: &Option<Range>,
+) -> Result<Stats, Error>
Expand description

Execute a spec, or a range of a spec.

+
\ No newline at end of file diff --git a/vidformer/fn.validate.html b/vidformer/fn.validate.html new file mode 100644 index 0000000..cb0e367 --- /dev/null +++ b/vidformer/fn.validate.html @@ -0,0 +1,6 @@ +validate in vidformer - Rust
vidformer

Function validate

source
pub fn validate(
+    spec: &Arc<Box<dyn Spec>>,
+    context: &Arc<Context>,
+    config: &Arc<Config>,
+) -> Result<(), Error>
Expand description

Validate that a spec can be run.

+
\ No newline at end of file diff --git a/vidformer/index.html b/vidformer/index.html new file mode 100644 index 0000000..49dd99c --- /dev/null +++ b/vidformer/index.html @@ -0,0 +1,9 @@ +vidformer - Rust

Crate vidformer

source
Expand description

vidformer is a core video synthesis/transformation library. +It handles the movement, control flow, and processing of video and conventional (non-video) data.

+

Quick links:

+ +

Modules§

  • Arrays provide access to data.
  • Filters create and transform video frames
  • Services provide access to media storage.
  • Spec Intermediate Representation
  • Specs declarativly define an edited video.

Structs§

Enums§

  • Select whether the output timestamps are local to the ranged segment or the entire output

Functions§

\ No newline at end of file diff --git a/vidformer/service/index.html b/vidformer/service/index.html new file mode 100644 index 0000000..9304b8a --- /dev/null +++ b/vidformer/service/index.html @@ -0,0 +1,2 @@ +vidformer::service - Rust
vidformer

Module service

source
Expand description

Services provide access to media storage.

+

Structs§

\ No newline at end of file diff --git a/vidformer/service/sidebar-items.js b/vidformer/service/sidebar-items.js new file mode 100644 index 0000000..02c1602 --- /dev/null +++ b/vidformer/service/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["Service"]}; \ No newline at end of file diff --git a/vidformer/service/struct.Service.html b/vidformer/service/struct.Service.html new file mode 100644 index 0000000..fccc58b --- /dev/null +++ b/vidformer/service/struct.Service.html @@ -0,0 +1,24 @@ +Service in vidformer::service - Rust
vidformer::service

Struct Service

source
pub struct Service { /* private fields */ }

Implementations§

source§

impl Service

source

pub fn new(service: String, config: HashMap<String, String>) -> Self

Trait Implementations§

source§

impl Clone for Service

source§

fn clone(&self) -> Service

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Service

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Service

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl<'de> Deserialize<'de> for Service

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Serialize for Service

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/sidebar-items.js b/vidformer/sidebar-items.js new file mode 100644 index 0000000..2caffdf --- /dev/null +++ b/vidformer/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["Error","RangeTsFormat"],"fn":["codecs","create_spec_hls","init","run","validate"],"mod":["array","filter","service","sir","source","spec"],"struct":["CodecDescriptor","Config","Context","EncoderConfig","Range","Stats"]}; \ No newline at end of file diff --git a/vidformer/sir/enum.DataExpr.html b/vidformer/sir/enum.DataExpr.html new file mode 100644 index 0000000..b8249b3 --- /dev/null +++ b/vidformer/sir/enum.DataExpr.html @@ -0,0 +1,33 @@ +DataExpr in vidformer::sir - Rust
vidformer::sir

Enum DataExpr

source
pub enum DataExpr {
+    Bool(bool),
+    Int(i64),
+    String(String),
+    Bytes(Vec<u8>),
+    ArrayRef(String, IndexConst),
+    Float(f64),
+    List(Vec<DataExpr>),
+}

Variants§

§

Bool(bool)

§

Int(i64)

§

String(String)

§

Bytes(Vec<u8>)

§

ArrayRef(String, IndexConst)

§

Float(f64)

§

List(Vec<DataExpr>)

Trait Implementations§

source§

impl Clone for DataExpr

source§

fn clone(&self) -> DataExpr

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for DataExpr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for DataExpr

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for DataExpr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Serialize for DataExpr

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/sir/enum.Expr.html b/vidformer/sir/enum.Expr.html new file mode 100644 index 0000000..21bac69 --- /dev/null +++ b/vidformer/sir/enum.Expr.html @@ -0,0 +1,28 @@ +Expr in vidformer::sir - Rust
vidformer::sir

Enum Expr

source
pub enum Expr {
+    Frame(FrameExpr),
+    Data(DataExpr),
+}

Variants§

Trait Implementations§

source§

impl Clone for Expr

source§

fn clone(&self) -> Expr

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Expr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Expr

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Expr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Serialize for Expr

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl Freeze for Expr

§

impl RefUnwindSafe for Expr

§

impl Send for Expr

§

impl Sync for Expr

§

impl Unpin for Expr

§

impl UnwindSafe for Expr

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/sir/enum.FrameExpr.html b/vidformer/sir/enum.FrameExpr.html new file mode 100644 index 0000000..1af72b8 --- /dev/null +++ b/vidformer/sir/enum.FrameExpr.html @@ -0,0 +1,28 @@ +FrameExpr in vidformer::sir - Rust
vidformer::sir

Enum FrameExpr

source
pub enum FrameExpr {
+    Source(FrameSource),
+    Filter(FilterExpr),
+}

Variants§

Trait Implementations§

source§

impl Clone for FrameExpr

source§

fn clone(&self) -> FrameExpr

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for FrameExpr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for FrameExpr

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for FrameExpr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Serialize for FrameExpr

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/sir/enum.IndexConst.html b/vidformer/sir/enum.IndexConst.html new file mode 100644 index 0000000..9ee6e59 --- /dev/null +++ b/vidformer/sir/enum.IndexConst.html @@ -0,0 +1,35 @@ +IndexConst in vidformer::sir - Rust
vidformer::sir

Enum IndexConst

source
pub enum IndexConst {
+    ILoc(usize),
+    T(Rational64),
+}

Variants§

Trait Implementations§

source§

impl Clone for IndexConst

source§

fn clone(&self) -> IndexConst

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for IndexConst

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for IndexConst

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for IndexConst

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Ord for IndexConst

source§

fn cmp(&self, other: &IndexConst) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where + Self: Sized,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for IndexConst

source§

fn eq(&self, other: &IndexConst) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
source§

impl PartialOrd for IndexConst

source§

fn partial_cmp(&self, other: &IndexConst) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the +<= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > +operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by +the >= operator. Read more
source§

impl Serialize for IndexConst

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl Eq for IndexConst

source§

impl StructuralPartialEq for IndexConst

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/sir/index.html b/vidformer/sir/index.html new file mode 100644 index 0000000..9d562bf --- /dev/null +++ b/vidformer/sir/index.html @@ -0,0 +1,4 @@ +vidformer::sir - Rust
vidformer

Module sir

source
Expand description

Spec Intermediate Representation

+

The SIR is a high-level representation of constructing a video frame from source frames and data. +This is the primary interface between specs and the rest of the system.

+

Structs§

Enums§

\ No newline at end of file diff --git a/vidformer/sir/sidebar-items.js b/vidformer/sir/sidebar-items.js new file mode 100644 index 0000000..6ca21fe --- /dev/null +++ b/vidformer/sir/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["DataExpr","Expr","FrameExpr","IndexConst"],"struct":["FilterExpr","FrameSource"]}; \ No newline at end of file diff --git a/vidformer/sir/struct.FilterExpr.html b/vidformer/sir/struct.FilterExpr.html new file mode 100644 index 0000000..1ebedf3 --- /dev/null +++ b/vidformer/sir/struct.FilterExpr.html @@ -0,0 +1,28 @@ +FilterExpr in vidformer::sir - Rust
vidformer::sir

Struct FilterExpr

source
pub struct FilterExpr {
+    pub name: String,
+    pub args: Vec<Expr>,
+    pub kwargs: BTreeMap<String, Expr>,
+}

Fields§

§name: String§args: Vec<Expr>§kwargs: BTreeMap<String, Expr>

Trait Implementations§

source§

impl Clone for FilterExpr

source§

fn clone(&self) -> FilterExpr

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for FilterExpr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for FilterExpr

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Serialize for FilterExpr

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/sir/struct.FrameSource.html b/vidformer/sir/struct.FrameSource.html new file mode 100644 index 0000000..31b20ee --- /dev/null +++ b/vidformer/sir/struct.FrameSource.html @@ -0,0 +1,31 @@ +FrameSource in vidformer::sir - Rust
vidformer::sir

Struct FrameSource

source
pub struct FrameSource { /* private fields */ }

Implementations§

source§

impl FrameSource

source

pub fn new(video: String, index: IndexConst) -> Self

source

pub fn video(&self) -> &str

source

pub fn index(&self) -> &IndexConst

Trait Implementations§

source§

impl Clone for FrameSource

source§

fn clone(&self) -> FrameSource

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for FrameSource

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for FrameSource

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Ord for FrameSource

source§

fn cmp(&self, other: &FrameSource) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where + Self: Sized,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for FrameSource

source§

fn eq(&self, other: &FrameSource) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
source§

impl PartialOrd for FrameSource

source§

fn partial_cmp(&self, other: &FrameSource) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the +<= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > +operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by +the >= operator. Read more
source§

impl Serialize for FrameSource

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl Eq for FrameSource

source§

impl StructuralPartialEq for FrameSource

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/source/fn.create_profile_file.html b/vidformer/source/fn.create_profile_file.html new file mode 100644 index 0000000..3d0ca60 --- /dev/null +++ b/vidformer/source/fn.create_profile_file.html @@ -0,0 +1 @@ +create_profile_file in vidformer::source - Rust
vidformer::source

Function create_profile_file

source
pub fn create_profile_file(streams: &[SourceVideoStreamMeta]) -> SourceFileMeta
\ No newline at end of file diff --git a/vidformer/source/index.html b/vidformer/source/index.html new file mode 100644 index 0000000..4e2fca0 --- /dev/null +++ b/vidformer/source/index.html @@ -0,0 +1 @@ +vidformer::source - Rust
\ No newline at end of file diff --git a/vidformer/source/sidebar-items.js b/vidformer/source/sidebar-items.js new file mode 100644 index 0000000..4e8ac54 --- /dev/null +++ b/vidformer/source/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["create_profile_file"],"struct":["SourceFileMeta","SourceVideoStreamMeta"]}; \ No newline at end of file diff --git a/vidformer/source/struct.SourceFileMeta.html b/vidformer/source/struct.SourceFileMeta.html new file mode 100644 index 0000000..19ef073 --- /dev/null +++ b/vidformer/source/struct.SourceFileMeta.html @@ -0,0 +1,22 @@ +SourceFileMeta in vidformer::source - Rust
vidformer::source

Struct SourceFileMeta

source
pub struct SourceFileMeta { /* private fields */ }

Trait Implementations§

source§

impl Debug for SourceFileMeta

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for SourceFileMeta

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Serialize for SourceFileMeta

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/source/struct.SourceVideoStreamMeta.html b/vidformer/source/struct.SourceVideoStreamMeta.html new file mode 100644 index 0000000..1b1bcd5 --- /dev/null +++ b/vidformer/source/struct.SourceVideoStreamMeta.html @@ -0,0 +1,45 @@ +SourceVideoStreamMeta in vidformer::source - Rust
vidformer::source

Struct SourceVideoStreamMeta

source
pub struct SourceVideoStreamMeta {
+    pub name: String,
+    pub file_path: String,
+    pub stream_idx: usize,
+    pub service: Service,
+    pub file_size: u64,
+    pub resolution: (usize, usize),
+    pub codec: String,
+    pub pix_fmt: String,
+    pub ts: Vec<Rational64>,
+    pub keys: Vec<Rational64>,
+}

Fields§

§name: String§file_path: String§stream_idx: usize§service: Service§file_size: u64§resolution: (usize, usize)§codec: String§pix_fmt: String§ts: Vec<Rational64>§keys: Vec<Rational64>

Implementations§

source§

impl SourceVideoStreamMeta

source

pub fn profile( + source_name: &str, + vid_path: &str, + stream: usize, + service: &Service, +) -> Result<Self, Error>

source

pub fn validate( + source_name: &str, + vid_path: &str, + stream: usize, + service: &Service, +)

Trait Implementations§

source§

impl Clone for SourceVideoStreamMeta

source§

fn clone(&self) -> SourceVideoStreamMeta

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for SourceVideoStreamMeta

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for SourceVideoStreamMeta

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Serialize for SourceVideoStreamMeta

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/spec/index.html b/vidformer/spec/index.html new file mode 100644 index 0000000..2de1108 --- /dev/null +++ b/vidformer/spec/index.html @@ -0,0 +1,7 @@ +vidformer::spec - Rust
vidformer

Module spec

source
Expand description

Specs declarativly define an edited video.

+

A spec defines an output video (as a logical time-indexed array). +It creates this array by defining its domain (the set of times at which the spec is defined) and a function that maps each time to a frame. +The frame is represented as an FrameExpr expression.

+

Specs are stateless and immutable. They are intended to be smaller than just storing the entire output video as an array. +Additionally, this generic spec interface allows the general case of a video-editing DSL, as done in V2V, while allowing for whatever language the use case needs.

+

Structs§

Traits§

  • A trait for a spec
  • A trait for providing information to a spec during runtime
\ No newline at end of file diff --git a/vidformer/spec/sidebar-items.js b/vidformer/spec/sidebar-items.js new file mode 100644 index 0000000..0569bf6 --- /dev/null +++ b/vidformer/spec/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["JsonSpec"],"trait":["Spec","SpecContext"]}; \ No newline at end of file diff --git a/vidformer/spec/struct.JsonSpec.html b/vidformer/spec/struct.JsonSpec.html new file mode 100644 index 0000000..89e3c76 --- /dev/null +++ b/vidformer/spec/struct.JsonSpec.html @@ -0,0 +1,25 @@ +JsonSpec in vidformer::spec - Rust
vidformer::spec

Struct JsonSpec

source
pub struct JsonSpec {
+    pub frames: Vec<(Rational64, FrameExpr)>,
+}
Expand description

A spec backed by a JSON file

+

Fields§

§frames: Vec<(Rational64, FrameExpr)>

Trait Implementations§

source§

impl Debug for JsonSpec

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for JsonSpec

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Serialize for JsonSpec

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl Spec for JsonSpec

source§

fn domain(&self, _context: &dyn SpecContext) -> Vec<Rational64>

Returns the domain of the spec. Read more
source§

fn render(&self, _context: &dyn SpecContext, t: &Rational64) -> FrameExpr

Returns the “logically” rendered frame at a given time. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/spec/trait.Spec.html b/vidformer/spec/trait.Spec.html new file mode 100644 index 0000000..f7f76bc --- /dev/null +++ b/vidformer/spec/trait.Spec.html @@ -0,0 +1,19 @@ +Spec in vidformer::spec - Rust
vidformer::spec

Trait Spec

source
pub trait Spec: Sync + Send {
+    // Required methods
+    fn domain(&self, context: &dyn SpecContext) -> Vec<Rational64>;
+    fn render(&self, context: &dyn SpecContext, t: &Rational64) -> FrameExpr;
+}
Expand description

A trait for a spec

+

A spec defines a video from a sequence of transformations. +A SpecContext is provided for information about the available source videos and arrays.

+

Required Methods§

source

fn domain(&self, context: &dyn SpecContext) -> Vec<Rational64>

Returns the domain of the spec.

+

The domain is the set of times at which the spec is defined. +Each time corresponds to a single output frame at that timestamp.

+

The output must:

+
    +
  • Be sorted in ascending order
  • +
  • Contain no duplicate values
  • +
  • Begin with 0
  • +
+
source

fn render(&self, context: &dyn SpecContext, t: &Rational64) -> FrameExpr

Returns the “logically” rendered frame at a given time.

+

This function should assume that the time is in the domain of the spec.

+

Implementors§

\ No newline at end of file diff --git a/vidformer/spec/trait.SpecContext.html b/vidformer/spec/trait.SpecContext.html new file mode 100644 index 0000000..1e5ef92 --- /dev/null +++ b/vidformer/spec/trait.SpecContext.html @@ -0,0 +1,2 @@ +SpecContext in vidformer::spec - Rust
vidformer::spec

Trait SpecContext

source
pub trait SpecContext { }
Expand description

A trait for providing information to a spec during runtime

+

Implementors§

\ No newline at end of file diff --git a/vidformer/struct.CodecDescriptor.html b/vidformer/struct.CodecDescriptor.html new file mode 100644 index 0000000..81ce152 --- /dev/null +++ b/vidformer/struct.CodecDescriptor.html @@ -0,0 +1,25 @@ +CodecDescriptor in vidformer - Rust
vidformer

Struct CodecDescriptor

source
pub struct CodecDescriptor {
+    pub name: String,
+    pub long_name: String,
+    pub format_id_pretty_name: String,
+    pub has_decoder: bool,
+    pub has_encoder: bool,
+}

Fields§

§name: String§long_name: String§format_id_pretty_name: String§has_decoder: bool§has_encoder: bool

Trait Implementations§

source§

impl Debug for CodecDescriptor

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/struct.Config.html b/vidformer/struct.Config.html new file mode 100644 index 0000000..8a29d47 --- /dev/null +++ b/vidformer/struct.Config.html @@ -0,0 +1,46 @@ +Config in vidformer - Rust
vidformer

Struct Config

source
pub struct Config {
+    pub decode_pool_size: usize,
+    pub decoder_view: usize,
+    pub decoders: usize,
+    pub filterers: usize,
+    pub output_width: usize,
+    pub output_height: usize,
+    pub output_pix_fmt: String,
+    pub encoder: Option<EncoderConfig>,
+    pub format: Option<String>,
+}
Expand description

Config for a spesific run of a vidformer spec

+

This is a collection of settings that are used to execute a spec. +This combines information about the output with internal performance knobs.

+

The max number of frames in memory is roughly decoders + decode_pool_size + decoder_view

+

Fields§

§decode_pool_size: usize

The number of frames which can be fit in the decode pool

+
§decoder_view: usize

How many output frames can be active at once +This also limits how many frames can be in the filters + encode buffer at once

+
§decoders: usize

How many decoders can be active at once

+
§filterers: usize

How many filter threads to run

+
§output_width: usize§output_height: usize§output_pix_fmt: String§encoder: Option<EncoderConfig>

Configuration to use for output encoder

+
§format: Option<String>

The name of the format to use for output. +If None, the format will be inferred from the output path.

+

Trait Implementations§

source§

impl Clone for Config

source§

fn clone(&self) -> Config

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Config

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Config

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Serialize for Config

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl Freeze for Config

§

impl RefUnwindSafe for Config

§

impl Send for Config

§

impl Sync for Config

§

impl Unpin for Config

§

impl UnwindSafe for Config

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/struct.Context.html b/vidformer/struct.Context.html new file mode 100644 index 0000000..bca8599 --- /dev/null +++ b/vidformer/struct.Context.html @@ -0,0 +1,27 @@ +Context in vidformer - Rust
vidformer

Struct Context

source
pub struct Context { /* private fields */ }
Expand description

A context for a spec

+

This is a collection of sources, filters, and arrays that are used to execute a DVE spec. +It’s a pretty simple layout here, but if you really want to incorporate vidformer deep into a VDBMS, you +gut this object and make the sources and arrays backed directly through your DB.

+

Implementations§

source§

impl Context

source

pub fn new( + source_files: Vec<SourceVideoStreamMeta>, + arrays: BTreeMap<String, Box<dyn Array>>, + filters: BTreeMap<String, Box<dyn Filter>>, +) -> Context

source

pub fn spec_ctx(&self) -> impl SpecContext

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/struct.EncoderConfig.html b/vidformer/struct.EncoderConfig.html new file mode 100644 index 0000000..bcef20d --- /dev/null +++ b/vidformer/struct.EncoderConfig.html @@ -0,0 +1,27 @@ +EncoderConfig in vidformer - Rust
vidformer

Struct EncoderConfig

source
pub struct EncoderConfig {
+    pub codec_name: String,
+    pub opts: Vec<(String, String)>,
+}

Fields§

§codec_name: String§opts: Vec<(String, String)>

Trait Implementations§

source§

impl Clone for EncoderConfig

source§

fn clone(&self) -> EncoderConfig

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for EncoderConfig

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for EncoderConfig

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Serialize for EncoderConfig

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/struct.Range.html b/vidformer/struct.Range.html new file mode 100644 index 0000000..3a14214 --- /dev/null +++ b/vidformer/struct.Range.html @@ -0,0 +1,27 @@ +Range in vidformer - Rust
vidformer

Struct Range

source
pub struct Range {
+    pub start: Rational64,
+    pub end: Rational64,
+    pub ts_format: RangeTsFormat,
+}
Expand description

A range spesifier

+

start and end are the start and end of the range in the timebase of the input, inclusive.

+

Fields§

§start: Rational64§end: Rational64§ts_format: RangeTsFormat

Trait Implementations§

source§

impl Clone for Range

source§

fn clone(&self) -> Range

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl Freeze for Range

§

impl RefUnwindSafe for Range

§

impl Send for Range

§

impl Sync for Range

§

impl Unpin for Range

§

impl UnwindSafe for Range

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/struct.Stats.html b/vidformer/struct.Stats.html new file mode 100644 index 0000000..40668b7 --- /dev/null +++ b/vidformer/struct.Stats.html @@ -0,0 +1,28 @@ +Stats in vidformer - Rust
vidformer

Struct Stats

source
pub struct Stats {
+    pub max_decoder_count: usize,
+    pub max_encode_buffer_size: usize,
+    pub decoders_created: usize,
+    pub frames_written: usize,
+    pub frames_decoded: usize,
+    pub runtime: Duration,
+}
Expand description

Stats from a run of a vidformer spec

+

Fields§

§max_decoder_count: usize§max_encode_buffer_size: usize§decoders_created: usize§frames_written: usize§frames_decoded: usize§runtime: Duration

Trait Implementations§

source§

impl Debug for Stats

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Serialize for Stats

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl Freeze for Stats

§

impl RefUnwindSafe for Stats

§

impl Send for Stats

§

impl Sync for Stats

§

impl Unpin for Stats

§

impl UnwindSafe for Stats

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where + V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where + T: 'static,

§

impl<T> MaybeSend for T
where + T: Send,

§

impl<T> MaybeSendSync for T

\ No newline at end of file diff --git a/vidformer/util/fn.codecs.html b/vidformer/util/fn.codecs.html new file mode 100644 index 0000000..27361d4 --- /dev/null +++ b/vidformer/util/fn.codecs.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/fn.codecs.html...

+ + + \ No newline at end of file diff --git a/vidformer/util/fn.init.html b/vidformer/util/fn.init.html new file mode 100644 index 0000000..d880a1f --- /dev/null +++ b/vidformer/util/fn.init.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/fn.init.html...

+ + + \ No newline at end of file diff --git a/vidformer/util/struct.CodecDescriptor.html b/vidformer/util/struct.CodecDescriptor.html new file mode 100644 index 0000000..50aa2f9 --- /dev/null +++ b/vidformer/util/struct.CodecDescriptor.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../vidformer/struct.CodecDescriptor.html...

+ + + \ No newline at end of file