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..91f4262 --- /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..c4af5d2 --- /dev/null +++ b/index.html @@ -0,0 +1,281 @@ + + + + + + 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..c4af5d2 --- /dev/null +++ b/introduction.html @@ -0,0 +1,281 @@ + + + + + + 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..89d86e1 --- /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 server for local use

    +
      +
    • Designed for local single-tenant use
    • +
    • Enables broad drop-in cv2 compatability
    • +
    • Supports basic Video on Demand hosting
    • +
    +
  • +
  • +

    igni: A vidformer server for the cloud

    +
      +
    • An in progress multi-tenant scale-out server
    • +
    • Designed for Video on Demand only +
        +
      • Does not support full-video exports
      • +
      • All video sources must be over the network, not local
      • +
      +
    • +
    • Enables live streaming and waiting on external dependencies for even lower time-to-playback latency
    • +
    +
  • +
+

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.

+

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:

+
    +
  • +

    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..743f736 --- /dev/null +++ b/roadmap.html @@ -0,0 +1,225 @@ + + + + + + Roadmap - vidformer - Video Data Transformation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

Roadmap

+

An unordered list of potential future features:

+
    +
  • +

    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..1e227c1 --- /dev/null +++ b/search-index.js @@ -0,0 +1,4 @@ +var searchIndex = new Map(JSON.parse('[["vidformer",{"t":"PFFPFFGPPPPPPPFGPPFPPCNNNNNNNNNNNNNNNNNNNNNNNNNNNNOHHOOOONNOOCONNNNNNOOOONNNNNNNNOOHNNNNNNNNOOOONOOOOHONNNCCCCNONNNNNNNNNNNNNNNNNNNNNONNNNNNNNHNNNNNNNNKFNNNMNNNMNMNNNNNNNPPKPFPFPPPPGNNNNNNCNNNNNNNNNCNNNMMNNNOONNNNOONNNNNNNNNNNNNNNNNNNNNNOOFFFFFFFFFFFFFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFFFFFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFNNNNNNNNNNNNNNNNNPPPPGGPFPPGFPGPPPPPNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFFNNNNNNNOHNNOONNNNNNOOONONNOONNNNNONNNNNFKKNNNMNNONNMNNNNNN","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","add_source_deps","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"],[633,"vidformer::source"],[674,"vidformer::spec"],[693,"vidformer::dve"],[694,"vidformer::util"],[695,"alloc::vec"],[696,"alloc::string"],[697,"num_rational"],[698,"core::result"],[699,"serde::de"],[700,"core::fmt"],[701,"alloc::boxed"],[702,"alloc::collections::btree::map"],[703,"alloc::sync"],[704,"core::option"],[705,"serde::ser"],[706,"core::any"],[707,"rusty_ffmpeg::ffi"],[708,"vidformer::filter::builtin::ipc"],[709,"std::collections::hash::map"],[710,"alloc::collections::btree::set"],[711,"core::cmp"]],"i":"Bf``0```0000000``j1`01`Aj2fhBl4lAb574326104361436143613``44424341`477432040225743261000`57432610022053444`2432````51436175743261057432610157432610`57432610``Db00C`1110101111111Dj0`0`0`0000`Dh1Dl120`120120120`100Cf023121231321231123123123123123123121```````````````EfEhEjElEnF`FbFdFfFhFjFlFnG`Ed>=<;:98765432100>=<;:987654321>=<;:987654321`0>=<;:9876543210>=<;:9876543210>>=<;:9876543210>=<;:9876543210>=<;:9876543210>>=<;:9876543210```````GbGdGfGhGjGlGn654321065432106543210`654321065432106543210654321065432106543210`H`0000000000000000Df00Hn``Hd`21``Hj`331301Hl1Hf14532014532014532014532014532020145320220144553320145302014531102020145320145324532014532014532014530201453``IbBn100000`100010101000000100001010010010```Id00Af111110111111","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{{bA`}n}000`{{}{{Ad{Ab}}}}{{{b{Af}}{b{Ah}}{b{Aj}}{b{f}}}{{B`{AlAlAl{Ad{{B`{AnAn}}}}}}}}````{c{{Bb{f}}}Bd}{c{{Bb{h}}}Bd}````{{{b{Bf}}{b{dBh}}}Bj}0{{{b{f}}{b{dBh}}}Bj}{{{b{h}}{b{dBh}}}Bj}{{{b{Bl}}{b{dBh}}}Bj}{{{b{Ab}}{b{dBh}}}Bj}````{cc{}}0000000``{{}n}{{}c{}}0000000````{{{Ad{Bn}}{Cd{Al{Cb{C`}}}}{Cd{Al{Cb{Cf}}}}}Aj}````{{{b{{Ch{{Cb{Af}}}}}}{b{Ah}}{b{{Ch{Aj}}}}{b{{Ch{f}}}}{b{{Cj{l}}}}}{{Bb{BlBf}}}}`{{{b{f}}c}BbCl}{{{b{h}}c}BbCl}{{{b{Bl}}c}BbCl}````{{{b{Aj}}}{{`{Cn}}}}`{bc{}}000{bAl}{c{{Bb{e}}}{}{}}0000000{{}{{Bb{c}}}{}}0000000`{bD`}0000000{{{b{{Ch{{Cb{Af}}}}}}{b{{Ch{Aj}}}}{b{{Ch{f}}}}}{{Bb{nBf}}}}{{}c{}}0000000``{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{c{{Bb{Db}}}Bd}{{{b{C`}}}{{Ad{An}}}}{{{b{Db}}}{{Ad{An}}}}{{{b{Db}}{b{dBh}}}Bj}{cc{}}{{{b{C`}}Dd}Df}{{{b{Db}}Dd}Df}{{{b{C`}}An}Df}{{{b{Db}}An}Df}{{}c{}}{{{b{Db}}c}BbCl}{c{{Bb{e}}}{}{}}{{}{{Bb{c}}}{}}{bD`}{{}c{}}````````````{b{{b{c}}}{}}00{{{b{d}}}{{b{dc}}}{}}00`{{{b{Dh}}}Dh}{{{b{Dj}}}Dj}{{{b{Dl}}}Dl}{{b{b{dc}}}n{}}00{{bA`}n}00`{c{{Bb{Dh}}}Bd}{c{{Bb{Dl}}}Bd}{{{b{Dl}}{b{Dl}}}Dn}{{{b{Cf}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Cf}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Dh}}{b{dBh}}}Bj}{{{b{Dj}}{b{dBh}}}Bj}{{{b{Dl}}{b{dBh}}}Bj}``{cc{}}00{{{b{Df}}{b{Aj}}}Dj}``{{}c{}}00{{DdDdEb}Dl}{{{b{Dh}}c}BbCl}{{{b{Dj}}c}BbCl}{{{b{Dl}}c}BbCl}{bc{}}00{c{{Bb{e}}}{}{}}00{{}{{Bb{c}}}{}}00{bD`}00{{}c{}}00`````````````````{b{{b{c}}}{}}00000000000000{{{b{d}}}{{b{dc}}}{}}00000000000000{c{{Bb{Ed}}}Bd}{{{b{Ef}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Eh}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Ej}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{El}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{En}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{F`}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Fb}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Fd}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Ff}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Fh}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Fj}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Fl}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Fn}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{G`}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Ef}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Eh}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Ej}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{El}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{En}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{F`}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Fb}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Fd}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Ff}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Fh}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Fj}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Fl}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Fn}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{G`}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{}{{Cd{Al{Cb{Cf}}}}}}{{{b{Ed}}{b{dBh}}}Bj}{cc{}}00000000000000{{}c{}}00000000000000{{AlAl}{{Bb{EfBf}}}}{c{{Bb{e}}}{}{}}00000000000000{{}{{Bb{c}}}{}}00000000000000{bD`}00000000000000{{{b{{Cd{AlAl}}}}}{{Bb{EfBf}}}}{{}c{}}00000000000000```````{b{{b{c}}}{}}000000{{{b{d}}}{{b{dc}}}{}}000000{{{b{Gb}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Gd}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Gf}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Gh}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Gj}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Gl}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Gn}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DhBf}}}}{{{b{Gb}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Gd}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Gf}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Gh}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Gj}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Gl}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{{b{Gn}}{b{{E`{Dj}}}}{b{{Cd{AlDj}}}}}{{Bb{DlBf}}}}{{}{{Cd{Al{Cb{Cf}}}}}}{cc{}}000000{{}c{}}000000{c{{Bb{e}}}{}{}}000000{{}{{Bb{c}}}{}}000000{bD`}000000{{}c{}}000000`{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{{{b{H`}}}H`}{{b{b{dc}}}n{}}{{bA`}n}{{}H`}{c{{Bb{H`}}}Bd}{{{b{H`}}{b{dBh}}}Bj}=<{{Al{Hb{AlAl}}}H`}{{{b{H`}}c}BbCl}{bc{}}>=<;```````````````````{{{b{Hd}}{b{d{Hh{{b{Hf}}}}}}}n}`;;;;;;::::::{{{b{Hj}}}Hj}{{{b{Hf}}}Hf}{{{b{Hl}}}Hl}{{{b{Hn}}}Hn}{{{b{Df}}}Df}{{{b{Hd}}}Hd}>>>>>>======{{{b{Hj}}{b{Hj}}}I`}{{{b{Hf}}{b{Hf}}}I`}{c{{Bb{Hj}}}Bd}{c{{Bb{Hf}}}Bd}{c{{Bb{Hl}}}Bd}{c{{Bb{Hn}}}Bd}{c{{Bb{Df}}}Bd}{c{{Bb{Hd}}}Bd}{{{b{Hj}}{b{Hj}}}Dn}{{{b{Hf}}{b{Hf}}}Dn}{{{b{Hj}}{b{dBh}}}Bj}0{{{b{Hf}}{b{dBh}}}Bj}{{{b{Hl}}{b{dBh}}}Bj}{{{b{Hn}}{b{dBh}}}Bj}0{{{b{Df}}{b{dBh}}}Bj}0{{{b{Hd}}{b{dBh}}}Bj}0{cc{}}00000{{{b{Hf}}}{{b{Hj}}}}{{}c{}}00000``{{AlHj}Hf}{{{b{Hj}}{b{Hj}}}{{Cj{I`}}}}{{{b{Hf}}{b{Hf}}}{{Cj{I`}}}}{{{b{Hj}}c}BbCl}{{{b{Hf}}c}BbCl}{{{b{Hl}}c}BbCl}{{{b{Hn}}c}BbCl}{{{b{Df}}c}BbCl}{{{b{Hd}}c}BbCl}{bc{}}00000{bAl}000{c{{Bb{e}}}{}{}}00000{{}{{Bb{c}}}{}}00000{bD`}00000{{{b{Hf}}}{{b{Ah}}}}{{}c{}}00000``{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{{b{Bn}}}Bn}{{b{b{dc}}}n{}}{{bA`}n}`{{{b{{E`{Bn}}}}}Ib}{c{{Bb{Ib}}}Bd}{c{{Bb{Bn}}}Bd}``{{{b{Ib}}{b{dBh}}}Bj}{{{b{Bn}}{b{dBh}}}Bj}{cc{}}0{{}c{}}0```{{{b{Ah}}{b{Ah}}Dd{b{H`}}}{{Bb{BnBf}}}}`{{{b{Ib}}c}BbCl}{{{b{Bn}}c}BbCl}``{bc{}}{c{{Bb{e}}}{}{}}0{{}{{Bb{c}}}{}}0`{bD`}0{{{b{Ah}}{b{Ah}}Dd{b{H`}}}n}{{}c{}}0```{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{c{{Bb{Id}}}Bd}{{{b{Af}}{b{Cn}}}{{Ad{An}}}}{{{b{Id}}{b{Cn}}}{{Ad{An}}}}{{{b{Id}}{b{dBh}}}Bj}`{cc{}}{{}c{}}{{{b{Af}}{b{Cn}}{b{An}}}Hd}{{{b{Id}}{b{Cn}}{b{An}}}Hd}{{{b{Id}}c}BbCl}?>=;","D":"A@f","p":[[1,"reference",null,null,1],[0,"mut"],[5,"Config",0,693],[5,"EncoderConfig",0,693],[6,"RangeTsFormat",0,693],[5,"Range",0,693],[1,"unit"],[1,"u8"],[5,"CodecDescriptor",0,694],[5,"Vec",695],[10,"Spec",674],[1,"str"],[5,"Context",0,693],[5,"String",696],[8,"Rational64",697],[1,"tuple",null,null,1],[6,"Result",698,null,1],[10,"Deserializer",699],[6,"Error",0,693],[5,"Formatter",700],[8,"Result",700],[5,"Stats",0,693],[5,"SourceVideoStreamMeta",633],[10,"Array",151],[5,"Box",701,null,1],[5,"BTreeMap",702],[10,"Filter",170],[5,"Arc",703,null,1],[6,"Option",704,null,1],[10,"Serializer",705],[10,"SpecContext",674],[5,"TypeId",706],[5,"JsonArary",151],[1,"usize"],[6,"DataExpr",503],[5,"Frame",170],[6,"Val",170],[5,"FrameType",170],[1,"bool"],[1,"slice"],[8,"AVPixelFormat",707],[5,"BoundingBoxBound",239],[5,"IPC",239,708],[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",709],[6,"FrameExpr",503],[5,"FrameSource",503],[5,"BTreeSet",710],[6,"IndexConst",503],[5,"FilterExpr",503],[6,"Expr",503],[6,"Ordering",711],[5,"SourceFileMeta",633],[5,"JsonSpec",674]],"r":[[1,694],[2,693],[4,693],[5,693],[6,693],[14,693],[15,693],[18,693],[51,694],[52,693],[83,694],[101,693],[142,693],[246,708]],"b":[[63,"impl-Debug-for-Error"],[64,"impl-Display-for-Error"],[564,"impl-Display-for-IndexConst"],[565,"impl-Debug-for-IndexConst"],[568,"impl-Debug-for-Expr"],[569,"impl-Display-for-Expr"],[570,"impl-Display-for-DataExpr"],[571,"impl-Debug-for-DataExpr"],[572,"impl-Display-for-FrameExpr"],[573,"impl-Debug-for-FrameExpr"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAADICKgABAAEABAAAAAYACAARAAEAFAABABcAHAA5AAIAPQAAAEAABQBHAAIAUgABAF0ACABnAAMAbQAAAG8AHwCQAAcAmgACAJ4AAQCiAAAApAAAAKYABgCuAAAAsAAFALcABQC+AAgAyAACAMwABQDVAAIA2wAbAPgAAgD8AD0AOwEAAFoBYADKASQA8QEZAAwCMgBFAgAATAI+AI8CEwCmAgIAqgICALACBQA=","P":[[22,"T"],[38,""],[42,"T"],[46,""],[57,"__D"],[63,""],[73,"T"],[83,""],[84,"U"],[96,""],[103,"__S"],[110,""],[112,"T"],[116,""],[117,"U,T"],[125,"U"],[134,""],[143,"V"],[153,"T"],[155,"__D"],[156,""],[159,"T"],[160,""],[164,"U"],[165,"__S"],[166,"U,T"],[167,"U"],[168,""],[169,"V"],[182,"T"],[189,""],[192,"T"],[195,""],[199,"D"],[200,"__D"],[201,""],[209,"T"],[212,""],[215,"U"],[218,""],[219,"S"],[220,"__S"],[222,"T"],[225,"U,T"],[228,"U"],[231,""],[234,"V"],[254,"T"],[284,"__D"],[285,""],[315,"T"],[330,"U"],[345,""],[346,"U,T"],[361,"U"],[376,""],[392,"V"],[414,"T"],[428,""],[443,"T"],[450,"U"],[457,"U,T"],[464,"U"],[471,""],[478,"V"],[486,"T"],[488,""],[489,"T"],[490,""],[492,"__D"],[493,""],[494,"T"],[495,"U"],[496,""],[497,"__S"],[498,"T"],[499,"U,T"],[500,"U"],[501,""],[502,"V"],[522,""],[524,"T"],[536,""],[542,"T"],[548,""],[556,"__D"],[562,""],[574,"T"],[580,""],[581,"U"],[589,""],[592,"__S"],[598,"T"],[604,""],[608,"U,T"],[614,"U"],[620,""],[627,"V"],[635,"T"],[639,""],[640,"T"],[641,""],[644,"__D"],[648,""],[650,"T"],[652,"U"],[657,""],[659,"__S"],[663,"T"],[664,"U,T"],[666,"U"],[669,""],[672,"V"],[677,"T"],[679,"__D"],[680,""],[684,"T"],[685,"U"],[686,""],[688,"__S"],[689,"U,T"],[690,"U"],[691,""],[692,"V"]]}]]')); +if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; +else if (window.initSearch) window.initSearch(searchIndex); +//{"start":39,"fragment_lengths":[15436]} \ 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..f862999 --- /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).\nAdd all referenced frame sources to a set.\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..277a067 --- /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":140,"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":92,"breadcrumbs":2,"title":1},"40":{"body":147,"breadcrumbs":7,"title":3},"41":{"body":17,"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 server for local use Designed for local single-tenant use Enables broad drop-in cv2 compatability Supports basic Video on Demand hosting igni : A vidformer server for the cloud An in progress multi-tenant scale-out server Designed for Video on Demand only Does not support full-video exports All video sources must be over the network, not local Enables live streaming and waiting on external dependencies for even lower time-to-playback latency 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.","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 + the yrden server ./vidformer-igni : The second generation vidformer server ./snake-pit : The main vidformer test suite ./viper-den : Igni server 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: 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":6,"docs":{"1":{"tf":1.0},"2":{"tf":1.0},"22":{"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":1,"docs":{"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":1,"docs":{"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}}},"i":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}}},"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":{"a":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"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.0},"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":{"23":{"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":3,"docs":{"12":{"tf":1.0},"23":{"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":4,"docs":{"1":{"tf":1.0},"18":{"tf":2.23606797749979},"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.0},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"2":{"tf":2.0},"23":{"tf":1.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":{},"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":{}},"n":{"df":1,"docs":{"4":{"tf":1.0}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"11":{"tf":1.0},"23":{"tf":1.0}}},"df":0,"docs":{}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"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":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}}},"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":5,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"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":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}},"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":3,"docs":{"10":{"tf":1.0},"23":{"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":2,"docs":{"22":{"tf":1.0},"23":{"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":{"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":1,"docs":{"1":{"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":3,"docs":{"23":{"tf":1.0},"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":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"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}}}}}}},"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":2,"docs":{"23":{"tf":1.0},"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},"4":{"tf":1.4142135623730951}}}}},"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":7,"docs":{"12":{"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":1,"docs":{"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":1.7320508075688772},"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":{},"n":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"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.0},"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}}}},"v":{"df":0,"docs":{},"e":{"df":1,"docs":{"23":{"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.7320508075688772},"44":{"tf":1.0},"9":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"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":1,"docs":{"23":{"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":3,"docs":{"18":{"tf":1.4142135623730951},"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":2,"docs":{"13":{"tf":1.0},"23":{"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":1,"docs":{"18":{"tf":1.4142135623730951}}}},"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":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"23":{"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":{},"y":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"1":{"tf":1.0},"23":{"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.0},"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.0}}},"df":0,"docs":{}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"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":{},"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":2,"docs":{"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}}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":9,"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},"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":{"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":3,"docs":{"23":{"tf":1.0},"32":{"tf":1.7320508075688772},"40":{"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":2,"docs":{"18":{"tf":1.7320508075688772},"4":{"tf":1.0}}},"df":0,"docs":{}}}},"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":1,"docs":{"45":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":8,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.7320508075688772},"23":{"tf":2.0},"33":{"tf":1.0},"4":{"tf":1.7320508075688772},"40":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":1.7320508075688772}}}},"i":{"c":{"df":2,"docs":{"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.0}}}}},"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":8,"docs":{"11":{"tf":1.0},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"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":2,"docs":{"1":{"tf":1.7320508075688772},"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}}}}}}},"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":1,"docs":{"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.7320508075688772}}}},"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":6,"docs":{"23":{"tf":1.4142135623730951},"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.4142135623730951},"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":1,"docs":{"23":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.4142135623730951}}}},"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":2,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0}},"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":1,"docs":{"1":{"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":0,"docs":{},"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.6457513110645907},"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":1,"docs":{"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":29,"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.4641016151377544},"40":{"tf":2.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}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"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":1.0}}},"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":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}},"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.0},"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":{}}},"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.0},"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.0}}}}}}},"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.0}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.0},"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":4,"docs":{"23":{"tf":1.4142135623730951},"4":{"tf":1.0},"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":6,"docs":{"1":{"tf":1.0},"2":{"tf":1.0},"22":{"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":1,"docs":{"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":1,"docs":{"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}}},"i":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}}},"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":{"a":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"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.0},"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":{"23":{"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":3,"docs":{"12":{"tf":1.0},"23":{"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":4,"docs":{"1":{"tf":1.0},"18":{"tf":2.23606797749979},"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":12,"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},"23":{"tf":1.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":{},"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":{}},"n":{"df":1,"docs":{"4":{"tf":1.0}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"11":{"tf":1.0},"23":{"tf":1.0}}},"df":0,"docs":{}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"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":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}}},"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":5,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"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":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}},"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":3,"docs":{"10":{"tf":1.0},"23":{"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":2,"docs":{"22":{"tf":1.0},"23":{"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":{"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":1,"docs":{"1":{"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":3,"docs":{"23":{"tf":1.0},"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":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"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}}}}}}},"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":2,"docs":{"23":{"tf":1.0},"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},"4":{"tf":1.4142135623730951}}}}},"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":7,"docs":{"12":{"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":1,"docs":{"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":1.7320508075688772},"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":{},"n":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"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.0},"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}}}},"v":{"df":0,"docs":{},"e":{"df":1,"docs":{"23":{"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.7320508075688772},"44":{"tf":1.0},"9":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"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":1,"docs":{"23":{"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":3,"docs":{"18":{"tf":1.4142135623730951},"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":2,"docs":{"13":{"tf":1.0},"23":{"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":1,"docs":{"18":{"tf":1.4142135623730951}}}},"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":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"23":{"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":{},"y":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"1":{"tf":1.0},"23":{"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.0},"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.0}}},"df":0,"docs":{}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"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":{},"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":2,"docs":{"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}}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":9,"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},"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":{"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":3,"docs":{"23":{"tf":1.0},"32":{"tf":2.0},"40":{"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":2,"docs":{"18":{"tf":1.7320508075688772},"4":{"tf":1.0}}},"df":0,"docs":{}}}},"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":1,"docs":{"45":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":8,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.7320508075688772},"23":{"tf":2.0},"33":{"tf":1.0},"4":{"tf":1.7320508075688772},"40":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":1.7320508075688772}}}},"i":{"c":{"df":2,"docs":{"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.0}}}}},"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":8,"docs":{"11":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"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":2,"docs":{"1":{"tf":1.7320508075688772},"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}}}}}}},"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":1,"docs":{"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.7320508075688772}}}},"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":6,"docs":{"23":{"tf":1.4142135623730951},"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.4142135623730951},"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":1,"docs":{"23":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.4142135623730951}}}},"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":2,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0}},"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":1,"docs":{"1":{"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":0,"docs":{},"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.6457513110645907},"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":1,"docs":{"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":29,"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.4641016151377544},"40":{"tf":2.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}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"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":1.0}}},"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":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}},"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.0},"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":{}}},"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.0},"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.0}}}}}}},"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.0}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.0},"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":4,"docs":{"23":{"tf":1.4142135623730951},"4":{"tf":1.0},"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..c6af127 --- /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":140,"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":92,"breadcrumbs":2,"title":1},"40":{"body":147,"breadcrumbs":7,"title":3},"41":{"body":17,"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 server for local use Designed for local single-tenant use Enables broad drop-in cv2 compatability Supports basic Video on Demand hosting igni : A vidformer server for the cloud An in progress multi-tenant scale-out server Designed for Video on Demand only Does not support full-video exports All video sources must be over the network, not local Enables live streaming and waiting on external dependencies for even lower time-to-playback latency 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.","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 + the yrden server ./vidformer-igni : The second generation vidformer server ./snake-pit : The main vidformer test suite ./viper-den : Igni server 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: 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":6,"docs":{"1":{"tf":1.0},"2":{"tf":1.0},"22":{"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":1,"docs":{"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":1,"docs":{"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}}},"i":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}}},"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":{"a":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"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.0},"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":{"23":{"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":3,"docs":{"12":{"tf":1.0},"23":{"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":4,"docs":{"1":{"tf":1.0},"18":{"tf":2.23606797749979},"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.0},"14":{"tf":1.7320508075688772},"15":{"tf":1.0},"2":{"tf":2.0},"23":{"tf":1.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":{},"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":{}},"n":{"df":1,"docs":{"4":{"tf":1.0}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"11":{"tf":1.0},"23":{"tf":1.0}}},"df":0,"docs":{}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"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":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}}},"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":5,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"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":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}},"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":3,"docs":{"10":{"tf":1.0},"23":{"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":2,"docs":{"22":{"tf":1.0},"23":{"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":{"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":1,"docs":{"1":{"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":3,"docs":{"23":{"tf":1.0},"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":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"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}}}}}}},"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":2,"docs":{"23":{"tf":1.0},"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},"4":{"tf":1.4142135623730951}}}}},"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":7,"docs":{"12":{"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":1,"docs":{"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":1.7320508075688772},"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":{},"n":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"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.0},"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}}}},"v":{"df":0,"docs":{},"e":{"df":1,"docs":{"23":{"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.7320508075688772},"44":{"tf":1.0},"9":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"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":1,"docs":{"23":{"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":3,"docs":{"18":{"tf":1.4142135623730951},"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":2,"docs":{"13":{"tf":1.0},"23":{"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":1,"docs":{"18":{"tf":1.4142135623730951}}}},"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":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"23":{"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":{},"y":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"1":{"tf":1.0},"23":{"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.0},"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.0}}},"df":0,"docs":{}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"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":{},"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":2,"docs":{"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}}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":9,"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},"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":{"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":3,"docs":{"23":{"tf":1.0},"32":{"tf":1.7320508075688772},"40":{"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":2,"docs":{"18":{"tf":1.7320508075688772},"4":{"tf":1.0}}},"df":0,"docs":{}}}},"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":1,"docs":{"45":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":8,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.7320508075688772},"23":{"tf":2.0},"33":{"tf":1.0},"4":{"tf":1.7320508075688772},"40":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":1.7320508075688772}}}},"i":{"c":{"df":2,"docs":{"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.0}}}}},"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":8,"docs":{"11":{"tf":1.0},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"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":2,"docs":{"1":{"tf":1.7320508075688772},"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}}}}}}},"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":1,"docs":{"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.7320508075688772}}}},"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":6,"docs":{"23":{"tf":1.4142135623730951},"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.4142135623730951},"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":1,"docs":{"23":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.4142135623730951}}}},"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":2,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0}},"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":1,"docs":{"1":{"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":0,"docs":{},"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.6457513110645907},"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":1,"docs":{"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":29,"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.4641016151377544},"40":{"tf":2.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}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"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":1.0}}},"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":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}},"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.0},"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":{}}},"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.0},"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.0}}}}}}},"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.0}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.0},"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":4,"docs":{"23":{"tf":1.4142135623730951},"4":{"tf":1.0},"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":6,"docs":{"1":{"tf":1.0},"2":{"tf":1.0},"22":{"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":1,"docs":{"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":1,"docs":{"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}}},"i":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}}}},"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":{"a":{"d":{"df":1,"docs":{"23":{"tf":1.0}}},"df":0,"docs":{}},"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.0},"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":{"23":{"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":3,"docs":{"12":{"tf":1.0},"23":{"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":4,"docs":{"1":{"tf":1.0},"18":{"tf":2.23606797749979},"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":12,"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},"23":{"tf":1.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":{},"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":{}},"n":{"df":1,"docs":{"4":{"tf":1.0}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"11":{"tf":1.0},"23":{"tf":1.0}}},"df":0,"docs":{}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.4142135623730951},"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":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}}},"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":5,"docs":{"1":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{}},"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":{},"n":{"df":1,"docs":{"23":{"tf":1.0}}},"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":3,"docs":{"10":{"tf":1.0},"23":{"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":2,"docs":{"22":{"tf":1.0},"23":{"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":{"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":1,"docs":{"1":{"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":3,"docs":{"23":{"tf":1.0},"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":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}},"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}}}}}}},"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":2,"docs":{"23":{"tf":1.0},"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},"4":{"tf":1.4142135623730951}}}}},"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":7,"docs":{"12":{"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":1,"docs":{"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":1.7320508075688772},"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":{},"n":{"c":{"df":1,"docs":{"23":{"tf":1.0}}},"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.0},"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}}}},"v":{"df":0,"docs":{},"e":{"df":1,"docs":{"23":{"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.7320508075688772},"44":{"tf":1.0},"9":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{},"w":{"df":1,"docs":{"23":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"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":1,"docs":{"23":{"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":3,"docs":{"18":{"tf":1.4142135623730951},"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":2,"docs":{"13":{"tf":1.0},"23":{"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":1,"docs":{"18":{"tf":1.4142135623730951}}}},"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":4,"docs":{"14":{"tf":1.0},"15":{"tf":1.0},"2":{"tf":1.0},"23":{"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":{},"y":{"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":2,"docs":{"1":{"tf":1.0},"23":{"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.0},"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.0}}},"df":0,"docs":{}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"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":{},"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":2,"docs":{"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}}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":9,"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},"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":{"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":3,"docs":{"23":{"tf":1.0},"32":{"tf":2.0},"40":{"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":2,"docs":{"18":{"tf":1.7320508075688772},"4":{"tf":1.0}}},"df":0,"docs":{}}}},"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":1,"docs":{"45":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":8,"docs":{"10":{"tf":1.4142135623730951},"18":{"tf":1.7320508075688772},"23":{"tf":2.0},"33":{"tf":1.0},"4":{"tf":1.7320508075688772},"40":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":1.7320508075688772}}}},"i":{"c":{"df":2,"docs":{"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.0}}}}},"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":8,"docs":{"11":{"tf":1.4142135623730951},"18":{"tf":1.4142135623730951},"22":{"tf":1.0},"23":{"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":2,"docs":{"1":{"tf":1.7320508075688772},"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}}}}}}},"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":1,"docs":{"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.7320508075688772}}}},"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":6,"docs":{"23":{"tf":1.4142135623730951},"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.4142135623730951},"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":1,"docs":{"23":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"4":{"tf":1.4142135623730951}}}},"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":2,"docs":{"18":{"tf":1.4142135623730951},"23":{"tf":1.0}},"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":1,"docs":{"1":{"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":0,"docs":{},"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.6457513110645907},"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":1,"docs":{"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":29,"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.4641016151377544},"40":{"tf":2.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}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"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":1.0}}},"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":{},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}},"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.0},"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":{}}},"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.0},"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.0}}}}}}},"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.0}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":2,"docs":{"23":{"tf":1.0},"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":4,"docs":{"23":{"tf":1.4142135623730951},"4":{"tf":1.0},"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..cf1ea43 --- /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..585b063 --- /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..8520ab4 --- /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..286a714 --- /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..a4049fb --- /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..5338f3d --- /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..e4d3198 --- /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..f156a46 --- /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..7263f2e --- /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_source_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..c799964 --- /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..d261315 --- /dev/null +++ b/src/vidformer/filter/builtin.rs.html @@ -0,0 +1,4009 @@ +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
+1970
+1971
+1972
+1973
+1974
+1975
+1976
+1977
+1978
+1979
+1980
+1981
+1982
+1983
+1984
+1985
+1986
+1987
+1988
+1989
+1990
+1991
+1992
+1993
+1994
+1995
+1996
+1997
+1998
+1999
+2000
+2001
+2002
+2003
+2004
//! 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 compression = match kwargs.get("compression") {
+            Some(Val::String(s)) => Option::Some(s),
+            _ => Option::None,
+        };
+
+        let mut data = match &args[0] {
+            Val::Bytes(b) => b,
+            _ => panic!("Expected bytes"),
+        };
+
+        let mut decompressed: Vec<u8> = Vec::new();
+        if let Some(compression) = compression {
+            assert_eq!(compression, "zlib");
+
+            let mut decoder = flate2::read::ZlibDecoder::new(&data[..]);
+            use std::io::Read;
+            decoder.read_to_end(&mut decompressed).unwrap();
+            data = &decompressed;
+            if data.len() != width as usize * height as usize * 3 {
+                return Err(Error::InvalidFilterArgValue(
+                    format!("{:?}", data.len()),
+                    "Invalid data length".to_string(),
+                ));
+            }
+        }
+
+        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),
+        };
+
+        let compression = match kwargs.get("compression") {
+            Some(Val::String(s)) => Option::Some(s),
+            _ => Option::None,
+        };
+
+        if let Some(compression) = compression {
+            if compression != "zlib" {
+                return Err(Error::InvalidFilterArgValue(
+                    compression.clone(),
+                    "Invalid compression".to_string(),
+                ));
+            }
+        }
+
+        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 compression.is_none() && 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..79de256 --- /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..39a1f1f --- /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..378c4df --- /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..05a0c8e --- /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..c2680bf --- /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..2d58439 --- /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..df761bf --- /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..24e0e32 --- /dev/null +++ b/src/vidformer/sir.rs.html @@ -0,0 +1,445 @@ +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
+222
//! 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_source_deps<'a>(&'a self, deps: &mut BTreeSet<&'a FrameSource>) {
+        match self {
+            Expr::Frame(frame) => {
+                frame.add_source_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 {
+    /// Add all referenced frame sources to a set.
+    pub fn add_source_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_source_deps(deps);
+                }
+                for arg in filter.kwargs.values() {
+                    arg.add_source_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..041ab48 --- /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..8ea8be6 --- /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..30f800f --- /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-eb44e4cf.txt b/static.files/COPYRIGHT-eb44e4cf.txt new file mode 100644 index 0000000..1447df7 --- /dev/null +++ b/static.files/COPYRIGHT-eb44e4cf.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-05ab6dbd.txt b/static.files/FiraSans-LICENSE-05ab6dbd.txt new file mode 100644 index 0000000..d7e9c14 --- /dev/null +++ b/static.files/FiraSans-LICENSE-05ab6dbd.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-e1aa3f0a.woff2 b/static.files/FiraSans-Medium-e1aa3f0a.woff2 new file mode 100644 index 0000000..7a1e5fc Binary files /dev/null and b/static.files/FiraSans-Medium-e1aa3f0a.woff2 differ diff --git a/static.files/FiraSans-Regular-0fe48ade.woff2 b/static.files/FiraSans-Regular-0fe48ade.woff2 new file mode 100644 index 0000000..e766e06 Binary files /dev/null and b/static.files/FiraSans-Regular-0fe48ade.woff2 differ diff --git a/static.files/LICENSE-APACHE-a60eea81.txt b/static.files/LICENSE-APACHE-a60eea81.txt new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/static.files/LICENSE-APACHE-a60eea81.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-23f18e03.txt b/static.files/LICENSE-MIT-23f18e03.txt new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/static.files/LICENSE-MIT-23f18e03.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-13b3dcba.ttf.woff2 b/static.files/NanumBarunGothic-13b3dcba.ttf.woff2 new file mode 100644 index 0000000..1866ad4 Binary files /dev/null and b/static.files/NanumBarunGothic-13b3dcba.ttf.woff2 differ diff --git a/static.files/NanumBarunGothic-LICENSE-a37d393b.txt b/static.files/NanumBarunGothic-LICENSE-a37d393b.txt new file mode 100644 index 0000000..4b3edc2 --- /dev/null +++ b/static.files/NanumBarunGothic-LICENSE-a37d393b.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-fc8b9304.ttf.woff2 b/static.files/SourceCodePro-It-fc8b9304.ttf.woff2 new file mode 100644 index 0000000..462c34e Binary files /dev/null and b/static.files/SourceCodePro-It-fc8b9304.ttf.woff2 differ diff --git a/static.files/SourceCodePro-LICENSE-67f54ca7.txt b/static.files/SourceCodePro-LICENSE-67f54ca7.txt new file mode 100644 index 0000000..0d2941e --- /dev/null +++ b/static.files/SourceCodePro-LICENSE-67f54ca7.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-8badfe75.ttf.woff2 b/static.files/SourceCodePro-Regular-8badfe75.ttf.woff2 new file mode 100644 index 0000000..10b558e Binary files /dev/null and b/static.files/SourceCodePro-Regular-8badfe75.ttf.woff2 differ diff --git a/static.files/SourceCodePro-Semibold-aa29a496.ttf.woff2 b/static.files/SourceCodePro-Semibold-aa29a496.ttf.woff2 new file mode 100644 index 0000000..5ec64ee Binary files /dev/null and b/static.files/SourceCodePro-Semibold-aa29a496.ttf.woff2 differ diff --git a/static.files/SourceSerif4-Bold-6d4fd4c0.ttf.woff2 b/static.files/SourceSerif4-Bold-6d4fd4c0.ttf.woff2 new file mode 100644 index 0000000..181a07f Binary files /dev/null and b/static.files/SourceSerif4-Bold-6d4fd4c0.ttf.woff2 differ diff --git a/static.files/SourceSerif4-It-ca3b17ed.ttf.woff2 b/static.files/SourceSerif4-It-ca3b17ed.ttf.woff2 new file mode 100644 index 0000000..2ae08a7 Binary files /dev/null and b/static.files/SourceSerif4-It-ca3b17ed.ttf.woff2 differ diff --git a/static.files/SourceSerif4-LICENSE-a2cfd9d5.md b/static.files/SourceSerif4-LICENSE-a2cfd9d5.md new file mode 100644 index 0000000..175fa4f --- /dev/null +++ b/static.files/SourceSerif4-LICENSE-a2cfd9d5.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-6b053e98.ttf.woff2 b/static.files/SourceSerif4-Regular-6b053e98.ttf.woff2 new file mode 100644 index 0000000..0263fc3 Binary files /dev/null and b/static.files/SourceSerif4-Regular-6b053e98.ttf.woff2 differ diff --git a/static.files/favicon-044be391.svg b/static.files/favicon-044be391.svg new file mode 100644 index 0000000..8b34b51 --- /dev/null +++ b/static.files/favicon-044be391.svg @@ -0,0 +1,24 @@ + + + + + diff --git a/static.files/favicon-32x32-6580c154.png b/static.files/favicon-32x32-6580c154.png new file mode 100644 index 0000000..69b8613 Binary files /dev/null and b/static.files/favicon-32x32-6580c154.png differ diff --git a/static.files/main-5f194d8c.js b/static.files/main-5f194d8c.js new file mode 100644 index 0000000..3d672cb --- /dev/null +++ b/static.files/main-5f194d8c.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-9960930a.css b/static.files/normalize-9960930a.css new file mode 100644 index 0000000..469959f --- /dev/null +++ b/static.files/normalize-9960930a.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-893ab5e7.css b/static.files/noscript-893ab5e7.css new file mode 100644 index 0000000..a6c18ec --- /dev/null +++ b/static.files/noscript-893ab5e7.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-9a9549ea.svg b/static.files/rust-logo-9a9549ea.svg new file mode 100644 index 0000000..62424d8 --- /dev/null +++ b/static.files/rust-logo-9a9549ea.svg @@ -0,0 +1,61 @@ + + + diff --git a/static.files/rustdoc-42caa33d.css b/static.files/rustdoc-42caa33d.css new file mode 100644 index 0000000..c1293a8 --- /dev/null +++ b/static.files/rustdoc-42caa33d.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-0fe48ade.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-e1aa3f0a.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-6b053e98.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-ca3b17ed.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-6d4fd4c0.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular-8badfe75.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:italic;font-weight:400;src:url("SourceCodePro-It-fc8b9304.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold-aa29a496.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'NanumBarunGothic';src:url("NanumBarunGothic-13b3dcba.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:15px;}.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,.sub-variant-field{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,.search-results li,.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,.type-signature{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,.docblock p code{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;margin-bottom:4px;}.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;margin:0;padding:0;}.search-results>a{display:grid;grid-template-areas:"search-result-name search-result-desc" "search-result-type-signature search-result-type-signature";grid-template-columns:.6fr .4fr;margin-left:2px;margin-right:2px;border-bottom:1px solid var(--search-result-border-color);column-gap:1em;}.search-results>a>div.desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;grid-area:search-result-desc;}.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;grid-area:search-result-name;}.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;}.search-results .type-signature{grid-area:search-result-type-signature;white-space:pre-wrap;}.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{width:0;visibility:hidden;}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-d508a8a9.js b/static.files/scrape-examples-d508a8a9.js new file mode 100644 index 0000000..87b6065 --- /dev/null +++ b/static.files/scrape-examples-d508a8a9.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-92e6798f.js b/static.files/search-92e6798f.js new file mode 100644 index 0000000..9260fd5 --- /dev/null +++ b/static.files/search-92e6798f.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 onEachBtwn(arr,func,funcBtwn){let skipped=true;for(const value of arr){if(!skipped){funcBtwn(value)}skipped=func(value)}}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_PRIMITIVE=itemTypes.indexOf("primitive");const TY_GENERIC=itemTypes.indexOf("generic");const TY_IMPORT=itemTypes.indexOf("import");const TY_TRAIT=itemTypes.indexOf("trait");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.normalizedPathLast;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(quadcolon!==null){throw["Unexpected ",quadcolon[0]]}const pathSegments=path.split(/(?:::\s*)|(?:\s+(?:::\s*)?)/).map(x=>x.toLowerCase());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.toLowerCase().replace(/_/g,""),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;let left=0;let right=this.keys.length-1;while(left<=right){const mid=Math.floor((left+right)/2);const x=this.keys[mid];if(xkey){right=mid-1}else{return this.containers[mid].contains(value)}}return false}}class RoaringBitmapRun{constructor(runcount,array){this.runcount=runcount;this.array=array}contains(value){let left=0;let right=this.runcount-1;while(left<=right){const mid=Math.floor((left+right)/2);const i=mid*4;const start=this.array[i]|(this.array[i+1]<<8);const lenm1=this.array[i+2]|(this.array[i+3]<<8);if((start+lenm1)value){right=mid-1}else{return true}}return false}}class RoaringBitmapArray{constructor(cardinality,array){this.cardinality=cardinality;this.array=array}contains(value){let left=0;let right=this.cardinality-1;while(left<=right){const mid=Math.floor((left+right)/2);const i=mid*2;const x=this.array[i]|(this.array[i+1]<<8);if(xvalue){right=mid-1}else{return true}}return false}}class RoaringBitmapBits{constructor(array){this.array=array}contains(value){return!!(this.array[value>>3]&(1<<(value&7)))}}class NameTrie{constructor(){this.children=[];this.matches=[]}insert(name,id,tailTable){this.insertSubstring(name,0,id,tailTable)}insertSubstring(name,substart,id,tailTable){const l=name.length;if(substart===l){this.matches.push(id)}else{const sb=name.charCodeAt(substart);let child;if(this.children[sb]!==undefined){child=this.children[sb]}else{child=new NameTrie();this.children[sb]=child;let sste;if(substart>=2){const tail=name.substring(substart-2,substart+1);if(tailTable.has(tail)){sste=tailTable.get(tail)}else{sste=[];tailTable.set(tail,sste)}sste.push(child)}}child.insertSubstring(name,substart+1,id,tailTable)}}search(name,tailTable){const results=new Set();this.searchSubstringPrefix(name,0,results);if(results.size=3){const levParams=name.length>=6?new Lev2TParametricDescription(name.length):new Lev1TParametricDescription(name.length);this.searchLev(name,0,levParams,results);const tail=name.substring(0,3);if(tailTable.has(tail)){for(const entry of tailTable.get(tail)){entry.searchSubstringPrefix(name,3,results)}}}return[...results]}searchSubstringPrefix(name,substart,results){const l=name.length;if(substart===l){for(const match of this.matches){results.add(match)}let unprocessedChildren=[];for(const child of this.children){if(child){unprocessedChildren.push(child)}}let nextSet=[];while(unprocessedChildren.length!==0){const next=unprocessedChildren.pop();for(const child of next.children){if(child){nextSet.push(child)}}for(const match of next.matches){results.add(match)}if(unprocessedChildren.length===0){const tmp=unprocessedChildren;unprocessedChildren=nextSet;nextSet=tmp}}}else{const sb=name.charCodeAt(substart);if(this.children[sb]!==undefined){this.children[sb].searchSubstringPrefix(name,substart+1,results)}}}searchLev(name,substart,levParams,results){const stack=[[this,0]];const n=levParams.n;while(stack.length!==0){const[trie,levState]=stack.pop();for(const[charCode,child]of trie.children.entries()){if(!child){continue}const levPos=levParams.getPosition(levState);const vector=levParams.getVector(name,charCode,levPos,Math.min(name.length,levPos+(2*n)+1),);const newLevState=levParams.transition(levState,levPos,vector,);if(newLevState>=0){stack.push([child,newLevState]);if(levParams.isAccept(newLevState)){for(const match of child.matches){results.add(match)}}}}}}}class DocSearch{constructor(rawSearchIndex,rootPath,searchState){this.searchIndexDeprecated=new Map();this.searchIndexEmptyDesc=new Map();this.functionTypeFingerprint=null;this.typeNameIdMap=new Map();this.assocTypeIdNameMap=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.typeNameIdOfOutput=this.buildTypeMapIndex("output",true);this.typeNameIdOfReference=this.buildTypeMapIndex("reference");this.EMPTY_BINDINGS_MAP=new Map();this.EMPTY_GENERICS_ARRAY=[];this.TYPES_POOL=new Map();this.nameTrie=new NameTrie();this.tailTable=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,paths,lowercasePaths){return types.length>0?types.map(type=>this.buildItemSearchType(type,paths,lowercasePaths)):this.EMPTY_GENERICS_ARRAY}buildItemSearchType(type,paths,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],paths,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,paths,lowercasePaths,true).id,this.buildItemSearchTypeAll(constraints,paths,lowercasePaths),]}))}else{bindings=this.EMPTY_BINDINGS_MAP}}let result;if(pathIndex<0){result={id:pathIndex,name:"",ty:TY_GENERIC,path:null,exactPath:null,generics,bindings,unboxFlag:true,}}else if(pathIndex===0){result={id:null,name:"",ty:null,path:null,exactPath:null,generics,bindings,unboxFlag:true,}}else{const item=lowercasePaths[pathIndex-1];const id=this.buildTypeMapIndex(item.name,isAssocType);if(isAssocType){this.assocTypeIdNameMap.set(id,paths[pathIndex-1].name)}result={id,name:paths[pathIndex-1].name,ty:item.ty,path:item.path,exactPath:item.exactPath,generics,bindings,unboxFlag:item.unboxFlag,}}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&&cr.name===result.name&&cr.unboxFlag===result.unboxFlag){return cr}}this.TYPES_POOL.set(result.id,result);return result}buildFunctionTypeFingerprint(type,output){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));output[3]+=1}for(const g of type.generics){this.buildFunctionTypeFingerprint(g,output)}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)}}buildIndex(rawSearchIndex){const buildFunctionSearchTypeCallback=(paths,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],paths,lowercasePaths,),]}else{inputs=this.buildItemSearchTypeAll(functionSearchType[INPUTS_DATA],paths,lowercasePaths,)}if(functionSearchType.length>1){if(typeof functionSearchType[OUTPUT_DATA]==="number"){output=[this.buildItemSearchType(functionSearchType[OUTPUT_DATA],paths,lowercasePaths,),]}else{output=this.buildItemSearchTypeAll(functionSearchType[OUTPUT_DATA],paths,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;let lastParamNames=[];let normalizedName=crate.indexOf("_")===-1?crate:crate.replace(/_/g,"");const crateRow={crate,ty:3,name:crate,path:"",descShard,descIndex,exactPath:"",desc:crateCorpus.doc,parent:undefined,type:null,paramNames:lastParamNames,id,word:crate,normalizedName,bitIndex:0,implDisambiguator:null,};this.nameTrie.insert(normalizedName,id,this.tailTable);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 itemParamNames=new Map(crateCorpus.P);const lowercasePaths=[];const itemFunctionDecoder=new VlqHexDecoder(crateCorpus.f,buildFunctionSearchTypeCallback(paths,lowercasePaths),);let len=paths.length;let lastPath=itemPaths.get(0);for(let i=0;i2&&elem[2]!==null){path=itemPaths.has(elem[2])?itemPaths.get(elem[2]):lastPath;lastPath=path}const exactPath=elem.length>3&&elem[3]!==null?itemPaths.get(elem[3]):path;const unboxFlag=elem.length>4&&!!elem[4];lowercasePaths.push({ty,name:name.toLowerCase(),path,exactPath,unboxFlag});paths[i]={ty,name,path,exactPath,unboxFlag}}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 paramNames=itemParamNames.has(i)?itemParamNames.get(i).split(","):lastParamNames;const type=itemFunctionDecoder.next();if(type!==null){if(type){const fp=this.functionTypeFingerprint.subarray(id*4,(id+1)*4);for(const t of type.inputs){this.buildFunctionTypeFingerprint(t,fp)}for(const t of type.output){this.buildFunctionTypeFingerprint(t,fp)}for(const w of type.where_clause){for(const t of w){this.buildFunctionTypeFingerprint(t,fp)}}}}const itemParentIdx=itemParentIdxDecoder.next();normalizedName=word.indexOf("_")===-1?word:word.replace(/_/g,"");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,paramNames,id,word,normalizedName,bitIndex,implDisambiguator:implDisambiguator.has(i)?implDisambiguator.get(i):null,};this.nameTrie.insert(normalizedName,id,this.tailTable);id+=1;searchIndex.push(row);lastPath=row.path;lastParamNames=row.paramNames;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{userQuery,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="";exactPath="";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+"::";exactPath=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,typeInfo)=>{const duplicates=new Set();const out=[];for(const result of results){if(result.id!==-1){const res=buildHrefAndPath(this.searchIndex[result.id]);const obj=Object.assign({dist:result.dist,displayPath:pathSplitter(res[0]),},this.searchIndex[result.id]);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]);if(typeInfo!==null){obj.displayTypeSignature=this.formatDisplayTypeSignature(obj,typeInfo)}obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}return out};this.formatDisplayTypeSignature=async(obj,typeInfo)=>{let fnInputs=null;let fnOutput=null;let mgens=null;if(typeInfo!=="elems"&&typeInfo!=="returned"){fnInputs=unifyFunctionTypes(obj.type.inputs,parsedQuery.elems,obj.type.where_clause,null,mgensScratch=>{fnOutput=unifyFunctionTypes(obj.type.output,parsedQuery.returned,obj.type.where_clause,mgensScratch,mgensOut=>{mgens=mgensOut;return true},0,);return!!fnOutput},0,)}else{const arr=typeInfo==="elems"?obj.type.inputs:obj.type.output;const highlighted=unifyFunctionTypes(arr,parsedQuery.elems,obj.type.where_clause,null,mgensOut=>{mgens=mgensOut;return true},0,);if(typeInfo==="elems"){fnInputs=highlighted}else{fnOutput=highlighted}}if(!fnInputs){fnInputs=obj.type.inputs}if(!fnOutput){fnOutput=obj.type.output}const mappedNames=new Map();const whereClause=new Map();const fnParamNames=obj.paramNames;const queryParamNames=[];const remapQuery=queryElem=>{if(queryElem.id<0){queryParamNames[-1-queryElem.id]=queryElem.name}if(queryElem.generics.length>0){queryElem.generics.forEach(remapQuery)}if(queryElem.bindings.size>0){[...queryElem.bindings.values()].flat().forEach(remapQuery)}};parsedQuery.elems.forEach(remapQuery);parsedQuery.returned.forEach(remapQuery);const pushText=(fnType,result)=>{if(!!(result.length%2)===!!fnType.highlighted){result.push("")}else if(result.length===0&&!!fnType.highlighted){result.push("");result.push("")}result[result.length-1]+=fnType.name};const writeHof=(fnType,result)=>{const hofOutput=fnType.bindings.get(this.typeNameIdOfOutput)||[];const hofInputs=fnType.generics;pushText(fnType,result);pushText({name:" (",highlighted:false},result);let needsComma=false;for(const fnType of hofInputs){if(needsComma){pushText({name:", ",highlighted:false},result)}needsComma=true;writeFn(fnType,result)}pushText({name:hofOutput.length===0?")":") -> ",highlighted:false,},result);if(hofOutput.length>1){pushText({name:"(",highlighted:false},result)}needsComma=false;for(const fnType of hofOutput){if(needsComma){pushText({name:", ",highlighted:false},result)}needsComma=true;writeFn(fnType,result)}if(hofOutput.length>1){pushText({name:")",highlighted:false},result)}};const writeSpecialPrimitive=(fnType,result)=>{if(fnType.id===this.typeNameIdOfArray||fnType.id===this.typeNameIdOfSlice||fnType.id===this.typeNameIdOfTuple||fnType.id===this.typeNameIdOfUnit){const[ob,sb]=fnType.id===this.typeNameIdOfArray||fnType.id===this.typeNameIdOfSlice?["[","]"]:["(",")"];pushText({name:ob,highlighted:fnType.highlighted},result);onEachBtwn(fnType.generics,nested=>writeFn(nested,result),()=>pushText({name:", ",highlighted:false},result),);pushText({name:sb,highlighted:fnType.highlighted},result);return true}else if(fnType.id===this.typeNameIdOfReference){pushText({name:"&",highlighted:fnType.highlighted},result);let prevHighlighted=false;onEachBtwn(fnType.generics,value=>{prevHighlighted=value.highlighted;writeFn(value,result)},value=>pushText({name:" ",highlighted:prevHighlighted&&value.highlighted,},result),);return true}else if(fnType.id===this.typeNameIdOfFn){writeHof(fnType,result);return true}return false};const writeFn=(fnType,result)=>{if(fnType.id<0){if(fnParamNames[-1-fnType.id]===""){for(const nested of fnType.generics){writeFn(nested,result)}return}else if(mgens){for(const[queryId,fnId]of mgens){if(fnId===fnType.id){mappedNames.set(queryParamNames[-1-queryId],fnParamNames[-1-fnType.id],)}}}pushText({name:fnParamNames[-1-fnType.id],highlighted:!!fnType.highlighted,},result);const where=[];onEachBtwn(fnType.generics,nested=>writeFn(nested,where),()=>pushText({name:" + ",highlighted:false},where),);if(where.length>0){whereClause.set(fnParamNames[-1-fnType.id],where)}}else{if(fnType.ty===TY_PRIMITIVE){if(writeSpecialPrimitive(fnType,result)){return}}else if(fnType.ty===TY_TRAIT&&(fnType.id===this.typeNameIdOfFn||fnType.id===this.typeNameIdOfFnMut||fnType.id===this.typeNameIdOfFnOnce)){writeHof(fnType,result);return}pushText(fnType,result);let hasBindings=false;if(fnType.bindings.size>0){onEachBtwn(fnType.bindings,([key,values])=>{const name=this.assocTypeIdNameMap.get(key);if(values.length===1&&values[0].id<0&&`${fnType.name}::${name}`===fnParamNames[-1-values[0].id]){for(const value of values){writeFn(value,[])}return true}if(!hasBindings){hasBindings=true;pushText({name:"<",highlighted:false},result)}pushText({name,highlighted:false},result);pushText({name:values.length!==1?"=(":"=",highlighted:false,},result);onEachBtwn(values||[],value=>writeFn(value,result),()=>pushText({name:" + ",highlighted:false},result),);if(values.length!==1){pushText({name:")",highlighted:false},result)}},()=>pushText({name:", ",highlighted:false},result),)}if(fnType.generics.length>0){pushText({name:hasBindings?", ":"<",highlighted:false},result)}onEachBtwn(fnType.generics,value=>writeFn(value,result),()=>pushText({name:", ",highlighted:false},result),);if(hasBindings||fnType.generics.length>0){pushText({name:">",highlighted:false},result)}}};const type=[];onEachBtwn(fnInputs,fnType=>writeFn(fnType,type),()=>pushText({name:", ",highlighted:false},type),);pushText({name:" -> ",highlighted:false},type);onEachBtwn(fnOutput,fnType=>writeFn(fnType,type),()=>pushText({name:", ",highlighted:false},type),);return{type,mappedNames,whereClause}};const sortResults=async(results,typeInfo,preferredCrate)=>{const userQuery=parsedQuery.userQuery;const normalizedUserQuery=parsedQuery.userQuery.toLowerCase();const isMixedCase=normalizedUserQuery!==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!==userQuery);b=(bbb.item.name!==userQuery);if(a!==b){return a-b}}a=(aaa.word!==normalizedUserQuery);b=(bbb.word!==normalizedUserQuery);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,typeInfo)};function unifyFunctionTypes(fnTypesIn,queryElems,whereClause,mgensIn,solutionCb,unboxingDepth,){if(unboxingDepth>=UNBOXING_LIMIT){return null}const mgens=mgensIn===null?null:new Map(mgensIn);if(queryElems.length===0){return solutionCb(mgens)?fnTypesIn:null}if(!fnTypesIn||fnTypesIn.length===0){return null}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[i,fnType]of fnTypesIn.entries()){if(!unifyFunctionTypeIsMatchCandidate(fnType,queryElem,mgens)){continue}if(fnType.id<0&&queryElem.id<0){if(mgens&&mgens.has(queryElem.id)&&mgens.get(queryElem.id)!==fnType.id){continue}const mgensScratch=new Map(mgens);mgensScratch.set(queryElem.id,fnType.id);if(!solutionCb||solutionCb(mgensScratch)){const highlighted=[...fnTypesIn];highlighted[i]=Object.assign({highlighted:true,},fnType,{generics:whereClause[-1-fnType.id],});return highlighted}}else if(solutionCb(mgens?new Map(mgens):null)){const highlighted=[...fnTypesIn];highlighted[i]=Object.assign({highlighted:true,},fnType,{generics:unifyGenericTypes(fnType.generics,queryElem.generics,whereClause,mgens?new Map(mgens):null,solutionCb,unboxingDepth,)||fnType.generics,});return highlighted}}for(const[i,fnType]of fnTypesIn.entries()){if(!unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth+1,)){continue}if(fnType.id<0){const highlightedGenerics=unifyFunctionTypes(whereClause[(-fnType.id)-1],queryElems,whereClause,mgens,solutionCb,unboxingDepth+1,);if(highlightedGenerics){const highlighted=[...fnTypesIn];highlighted[i]=Object.assign({highlighted:true,},fnType,{generics:highlightedGenerics,});return highlighted}}else{const highlightedGenerics=unifyFunctionTypes([...Array.from(fnType.bindings.values()).flat(),...fnType.generics],queryElems,whereClause,mgens?new Map(mgens):null,solutionCb,unboxingDepth+1,);if(highlightedGenerics){const highlighted=[...fnTypesIn];highlighted[i]=Object.assign({},fnType,{generics:highlightedGenerics,bindings:new Map([...fnType.bindings.entries()].map(([k,v])=>{return[k,highlightedGenerics.splice(0,v.length)]})),});return highlighted}}}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(queryElem.id)&&mgensScratch.get(queryElem.id)!==fnType.id){continue}mgensScratch.set(queryElem.id,fnType.id)}else{mgensScratch=mgens}fnTypes[i]=fnTypes[flast];fnTypes.length=flast;if(!queryElemsTmp){queryElemsTmp=queryElems.slice(0,qlast)}let unifiedGenerics=[];let unifiedGenericsMgens=null;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(mgensScratch)}const solution=unifyFunctionTypeCheckBindings(fnType,queryElem,whereClause,mgensScratch,unboxingDepth,);if(!solution){return false}const simplifiedGenerics=solution.simplifiedGenerics;for(const simplifiedMgens of solution.mgens){unifiedGenerics=unifyGenericTypes(simplifiedGenerics,queryElem.generics,whereClause,simplifiedMgens,solutionCb,unboxingDepth,);if(unifiedGenerics!==null){unifiedGenericsMgens=simplifiedMgens;return true}}return false},unboxingDepth,);if(passesUnification){passesUnification.length=fl;passesUnification[flast]=passesUnification[i];passesUnification[i]=Object.assign({},fnType,{highlighted:true,generics:unifiedGenerics,bindings:new Map([...fnType.bindings.entries()].map(([k,v])=>{return[k,queryElem.bindings.has(k)?unifyFunctionTypes(v,queryElem.bindings.get(k),whereClause,unifiedGenericsMgens,solutionCb,unboxingDepth,):unifiedGenerics.splice(0,v.length)]})),});return passesUnification}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}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,...bindings,...generics),queryElems,whereClause,mgens,solutionCb,unboxingDepth+1,);if(passesUnification){const highlightedGenerics=passesUnification.slice(i,i+generics.length+bindings.length,);const highlightedFnType=Object.assign({},fnType,{generics:highlightedGenerics,bindings:new Map([...fnType.bindings.entries()].map(([k,v])=>{return[k,highlightedGenerics.splice(0,v.length)]})),});return passesUnification.toSpliced(i,generics.length+bindings.length,highlightedFnType,)}}return null}function unifyGenericTypes(fnTypesIn,queryElems,whereClause,mgensIn,solutionCb,unboxingDepth,){if(unboxingDepth>=UNBOXING_LIMIT){return null}const mgens=mgensIn===null?null:new Map(mgensIn);if(queryElems.length===0){return solutionCb(mgens)?fnTypesIn:null}if(!fnTypesIn||fnTypesIn.length===0){return null}const fnType=fnTypesIn[0];const queryElem=queryElems[0];if(unifyFunctionTypeIsMatchCandidate(fnType,queryElem,mgens)){if(fnType.id<0&&queryElem.id<0){if(!mgens||!mgens.has(queryElem.id)||mgens.get(queryElem.id)===fnType.id){const mgensScratch=new Map(mgens);mgensScratch.set(queryElem.id,fnType.id);const fnTypesRemaining=unifyGenericTypes(fnTypesIn.slice(1),queryElems.slice(1),whereClause,mgensScratch,solutionCb,unboxingDepth,);if(fnTypesRemaining){const highlighted=[fnType,...fnTypesRemaining];highlighted[0]=Object.assign({highlighted:true,},fnType,{generics:whereClause[-1-fnType.id],});return highlighted}}}else{let unifiedGenerics;const fnTypesRemaining=unifyGenericTypes(fnTypesIn.slice(1),queryElems.slice(1),whereClause,mgens,mgensScratch=>{const solution=unifyFunctionTypeCheckBindings(fnType,queryElem,whereClause,mgensScratch,unboxingDepth,);if(!solution){return false}const simplifiedGenerics=solution.simplifiedGenerics;for(const simplifiedMgens of solution.mgens){unifiedGenerics=unifyGenericTypes(simplifiedGenerics,queryElem.generics,whereClause,simplifiedMgens,solutionCb,unboxingDepth,);if(unifiedGenerics!==null){return true}}},unboxingDepth,);if(fnTypesRemaining){const highlighted=[fnType,...fnTypesRemaining];highlighted[0]=Object.assign({highlighted:true,},fnType,{generics:unifiedGenerics||fnType.generics,});return highlighted}}}if(unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth+1,)){let highlightedRemaining;if(fnType.id<0){const highlightedGenerics=unifyFunctionTypes(whereClause[(-fnType.id)-1],[queryElem],whereClause,mgens,mgensScratch=>{const hl=unifyGenericTypes(fnTypesIn.slice(1),queryElems.slice(1),whereClause,mgensScratch,solutionCb,unboxingDepth,);if(hl){highlightedRemaining=hl}return hl},unboxingDepth+1,);if(highlightedGenerics){return[Object.assign({highlighted:true,},fnType,{generics:highlightedGenerics,}),...highlightedRemaining]}}else{const highlightedGenerics=unifyGenericTypes([...Array.from(fnType.bindings.values()).flat(),...fnType.generics,],[queryElem],whereClause,mgens,mgensScratch=>{const hl=unifyGenericTypes(fnTypesIn.slice(1),queryElems.slice(1),whereClause,mgensScratch,solutionCb,unboxingDepth,);if(hl){highlightedRemaining=hl}return hl},unboxingDepth+1,);if(highlightedGenerics){return[Object.assign({},fnType,{generics:highlightedGenerics,bindings:new Map([...fnType.bindings.entries()].map(([k,v])=>{return[k,highlightedGenerics.splice(0,v.length)]})),}),...highlightedRemaining]}}}return null}const unifyFunctionTypeIsMatchCandidate=(fnType,queryElem,mgensIn)=>{if(!typePassesFilter(queryElem.typeFilter,fnType.ty)){return false}if(fnType.id<0&&queryElem.id<0){if(mgensIn&&mgensIn.has(queryElem.id)&&mgensIn.get(queryElem.id)!==fnType.id){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=[...binds,...simplifiedGenerics]}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){if(!whereClause){return false}return checkIfInList(whereClause[(-fnType.id)-1],queryElem,whereClause,mgens,unboxingDepth,)}else if(fnType.unboxFlag&&(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.id>0&&elem.id>0&&elem.pathWithoutLast.length===0&&row.generics.length===0&&elem.generics.length===0&&row.bindings.size===0&&elem.bindings.size===0&&elem.id!==this.typeNameIdOfArrayOrSlice&&elem.id!==this.typeNameIdOfHof&&elem.id!==this.typeNameIdOfTupleOrUnit){return row.id===elem.id&&typePassesFilter(elem.typeFilter,row.ty)}else{return unifyFunctionTypes([row],[elem],whereClause,mgens,()=>true,unboxingDepth,)}};const checkTypeMgensForConflict=mgens=>{if(!mgens){return true}const fnTypes=new Set();for(const[_qid,fid]of mgens){if(fnTypes.has(fid)){return false}fnTypes.add(fid)}return true};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 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,checkTypeMgensForConflict,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.normalizedPathLast)){elem.id=genericSymbols.get(elem.normalizedPathLast)}else{elem.id=-(genericSymbols.size+1);genericSymbols.set(elem.normalizedPathLast,elem.id)}if(elem.typeFilter===-1&&elem.normalizedPathLast.length>=3){const maxPartDistance=Math.floor(elem.normalizedPathLast.length/3);let matchDist=maxPartDistance+1;let matchName="";for(const name of this.typeNameIdMap.keys()){const dist=editDistance(name,elem.normalizedPathLast,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]}),)};for(const elem of parsedQuery.elems){convertNameToId(elem);this.buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint)}for(const elem of parsedQuery.returned){convertNameToId(elem);this.buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint)}if(parsedQuery.foundElems===1&&!parsedQuery.hasReturnArrow){const elem=parsedQuery.elems[0];const handleNameSearch=id=>{const row=this.searchIndex[id];if(!typePassesFilter(elem.typeFilter,row.ty)||(filterCrates!==null&&row.crate!==filterCrates)){return}let pathDist=0;if(elem.fullPath.length>1){pathDist=checkPath(elem.pathWithoutLast,row);if(pathDist===null){return}}if(parsedQuery.literalSearch){if(row.word===elem.pathLast){addIntoResults(results_others,row.id,id,0,0,pathDist)}}else{addIntoResults(results_others,row.id,id,row.normalizedName.indexOf(elem.normalizedPathLast),editDistance(row.normalizedName,elem.normalizedPathLast,maxEditDistance,),pathDist,maxEditDistance,)}};if(elem.normalizedPathLast!==""){const last=elem.normalizedPathLast;for(const id of this.nameTrie.search(last,this.tailTable)){handleNameSearch(id)}}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(array.length===0&&query.error===null?"div":"ul",);if(array.length>0){output.className="search-results "+extraClass;const lis=Promise.all(array.map(async item=>{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("span");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);if(item.displayTypeSignature){const{type,mappedNames,whereClause}=await item.displayTypeSignature;const displayType=document.createElement("div");type.forEach((value,index)=>{if(index%2!==0){const highlight=document.createElement("strong");highlight.appendChild(document.createTextNode(value));displayType.appendChild(highlight)}else{displayType.appendChild(document.createTextNode(value))}});if(mappedNames.size>0||whereClause.size>0){let addWhereLineFn=()=>{const line=document.createElement("div");line.className="where";line.appendChild(document.createTextNode("where"));displayType.appendChild(line);addWhereLineFn=()=>{}};for(const[qname,name]of mappedNames){if(name===qname){continue}addWhereLineFn();const line=document.createElement("div");line.className="where";line.appendChild(document.createTextNode(` ${qname} matches `));const lineStrong=document.createElement("strong");lineStrong.appendChild(document.createTextNode(name));line.appendChild(lineStrong);displayType.appendChild(line)}for(const[name,innerType]of whereClause){if(innerType.length<=1){continue}addWhereLineFn();const line=document.createElement("div");line.className="where";line.appendChild(document.createTextNode(` ${name}: `));innerType.forEach((value,index)=>{if(index%2!==0){const highlight=document.createElement("strong");highlight.appendChild(document.createTextNode(value));line.appendChild(highlight)}else{line.appendChild(document.createTextNode(value))}});displayType.appendChild(line)}}displayType.className="type-signature";link.appendChild(displayType)}link.appendChild(description);return link}));lis.then(lis=>{for(const li of lis){output.appendChild(li)}})}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}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;let currentTab=searchState.currentTab;if((currentTab===0&&results.others.length===0)||(currentTab===1&&results.in_args.length===0)||(currentTab===2&&results.returned.length===0)){if(results.others.length!==0){currentTab=0}else if(results.in_args.length){currentTab=1}else if(results.returned.length){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",results.others.length)+"
";currentTab=0}else if(results.query.foundElems<=1&&results.query.returned.length===0){output+="
"+makeTabHeader(0,"In Names",results.others.length)+makeTabHeader(1,"In Parameters",results.in_args.length)+makeTabHeader(2,"In Return Types",results.returned.length)+"
"}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,results.others.length)+"
";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[ret_others,ret_in_args,ret_returned]=await Promise.all([addTab(results.others,results.query,currentTab===0),addTab(results.in_args,results.query,currentTab===1),addTab(results.returned,results.query,currentTab===2),]);const resultsElem=document.createElement("div");resultsElem.id="results";resultsElem.appendChild(ret_others);resultsElem.appendChild(ret_in_args);resultsElem.appendChild(ret_returned);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.userQuery+"\" Search - Rust";updateSearchHistory(buildUrl(query.userQuery,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())}class ParametricDescription{constructor(w,n,minErrors){this.w=w;this.n=n;this.minErrors=minErrors}isAccept(absState){const state=Math.floor(absState/(this.w+1));const offset=absState%(this.w+1);return this.w-offset+this.minErrors[state]<=this.n}getPosition(absState){return absState%(this.w+1)}getVector(name,charCode,pos,end){let vector=0;for(let i=pos;i>5;const bitStart=bitLoc&31;if(bitStart+bitsPerValue<=32){return((data[dataLoc]>>bitStart)&this.MASKS[bitsPerValue-1])}else{const part=32-bitStart;return ~~(((data[dataLoc]>>bitStart)&this.MASKS[part-1])+((data[1+dataLoc]&this.MASKS[bitsPerValue-part-1])<{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-56102188.js b/static.files/src-script-56102188.js new file mode 100644 index 0000000..d0aebb8 --- /dev/null +++ b/static.files/src-script-56102188.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-59e33391.js b/static.files/storage-59e33391.js new file mode 100644 index 0000000..5aac776 --- /dev/null +++ b/static.files/storage-59e33391.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..4087309 --- /dev/null +++ b/tools.html @@ -0,0 +1,255 @@ + + + + + + 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 server for local use

    +
      +
    • Designed for local single-tenant use
    • +
    • Enables broad drop-in cv2 compatability
    • +
    • Supports basic Video on Demand hosting
    • +
    +
  • +
  • +

    igni: A vidformer server for the cloud

    +
      +
    • An in progress multi-tenant scale-out server
    • +
    • Designed for Video on Demand only +
        +
      • Does not support full-video exports
      • +
      • All video sources must be over the network, not local
      • +
      +
    • +
    • Enables live streaming and waiting on external dependencies for even lower time-to-playback latency
    • +
    +
  • +
+

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.

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

Set the server to use for the cv2 frontend.

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

Return the frame as a numpy array.

+
+ + +
+
+
+ +
+ + class + VideoCapture: + + + +
+ +
242class VideoCapture:
+243    def __init__(self, path):
+244        server = _server()
+245        if type(path) == str:
+246            assert isinstance(server, vf.YrdenServer)
+247            self._path = path
+248            self._source = vf.Source(server, str(uuid.uuid4()), path, 0)
+249        elif isinstance(path, igni.IgniSource):
+250            assert isinstance(server, igni.IgniServer)
+251            self._path = path._name
+252            self._source = path
+253        self._next_frame_idx = 0
+254
+255    def isOpened(self):
+256        return True
+257
+258    def get(self, prop):
+259        if prop == CAP_PROP_FPS:
+260            return _ts_to_fps(self._source.ts())
+261        elif prop == CAP_PROP_FRAME_WIDTH:
+262            return self._source.fmt()["width"]
+263        elif prop == CAP_PROP_FRAME_HEIGHT:
+264            return self._source.fmt()["height"]
+265        elif prop == CAP_PROP_FRAME_COUNT:
+266            return len(self._source.ts())
+267        elif prop == CAP_PROP_POS_FRAMES:
+268            return self._next_frame_idx
+269
+270        raise Exception(f"Unknown property {prop}")
+271
+272    def set(self, prop, value):
+273        if prop == CAP_PROP_POS_FRAMES:
+274            assert value >= 0 and value < len(self._source.ts())
+275            self._next_frame_idx = value
+276        elif prop == CAP_PROP_POS_MSEC:
+277            t = Fraction(value, 1000)
+278            ts = self._source.ts()
+279            next_frame_idx = bisect_right(ts, t)
+280            self._next_frame_idx = next_frame_idx
+281        else:
+282            raise Exception(f"Unsupported property {prop}")
+283
+284    def read(self):
+285        if self._next_frame_idx >= len(self._source):
+286            return False, None
+287        frame = self._source.iloc[self._next_frame_idx]
+288        self._next_frame_idx += 1
+289        frame = Frame(frame, self._source.fmt())
+290        return True, frame
+291
+292    def release(self):
+293        pass
+
+ + + + +
+ +
+ + VideoCapture(path) + + + +
+ +
243    def __init__(self, path):
+244        server = _server()
+245        if type(path) == str:
+246            assert isinstance(server, vf.YrdenServer)
+247            self._path = path
+248            self._source = vf.Source(server, str(uuid.uuid4()), path, 0)
+249        elif isinstance(path, igni.IgniSource):
+250            assert isinstance(server, igni.IgniServer)
+251            self._path = path._name
+252            self._source = path
+253        self._next_frame_idx = 0
+
+ + + + +
+
+ +
+ + def + isOpened(self): + + + +
+ +
255    def isOpened(self):
+256        return True
+
+ + + + +
+
+ +
+ + def + get(self, prop): + + + +
+ +
258    def get(self, prop):
+259        if prop == CAP_PROP_FPS:
+260            return _ts_to_fps(self._source.ts())
+261        elif prop == CAP_PROP_FRAME_WIDTH:
+262            return self._source.fmt()["width"]
+263        elif prop == CAP_PROP_FRAME_HEIGHT:
+264            return self._source.fmt()["height"]
+265        elif prop == CAP_PROP_FRAME_COUNT:
+266            return len(self._source.ts())
+267        elif prop == CAP_PROP_POS_FRAMES:
+268            return self._next_frame_idx
+269
+270        raise Exception(f"Unknown property {prop}")
+
+ + + + +
+
+ +
+ + def + set(self, prop, value): + + + +
+ +
272    def set(self, prop, value):
+273        if prop == CAP_PROP_POS_FRAMES:
+274            assert value >= 0 and value < len(self._source.ts())
+275            self._next_frame_idx = value
+276        elif prop == CAP_PROP_POS_MSEC:
+277            t = Fraction(value, 1000)
+278            ts = self._source.ts()
+279            next_frame_idx = bisect_right(ts, t)
+280            self._next_frame_idx = next_frame_idx
+281        else:
+282            raise Exception(f"Unsupported property {prop}")
+
+ + + + +
+
+ +
+ + def + read(self): + + + +
+ +
284    def read(self):
+285        if self._next_frame_idx >= len(self._source):
+286            return False, None
+287        frame = self._source.iloc[self._next_frame_idx]
+288        self._next_frame_idx += 1
+289        frame = Frame(frame, self._source.fmt())
+290        return True, frame
+
+ + + + +
+
+ +
+ + def + release(self): + + + +
+ +
292    def release(self):
+293        pass
+
+ + + + +
+
+
+ +
+ + class + VideoWriter: + + + +
+ +
296class VideoWriter:
+297    def __init__(self, *args, **kwargs):
+298        server = _server()
+299        if isinstance(server, vf.YrdenServer):
+300            self._writer = _YrdenVideoWriter(*args, **kwargs)
+301        elif isinstance(server, igni.IgniServer):
+302            self._writer = _IgniVideoWriter(*args, **kwargs)
+303        else:
+304            raise Exception("Unsupported server type")
+305
+306    def write(self, *args, **kwargs):
+307        return self._writer.write(*args, **kwargs)
+308
+309    def release(self, *args, **kwargs):
+310        return self._writer.release(*args, **kwargs)
+311
+312    def spec(self, *args, **kwargs):
+313        return self._writer.spec(*args, **kwargs)
+
+ + + + +
+ +
+ + VideoWriter(*args, **kwargs) + + + +
+ +
297    def __init__(self, *args, **kwargs):
+298        server = _server()
+299        if isinstance(server, vf.YrdenServer):
+300            self._writer = _YrdenVideoWriter(*args, **kwargs)
+301        elif isinstance(server, igni.IgniServer):
+302            self._writer = _IgniVideoWriter(*args, **kwargs)
+303        else:
+304            raise Exception("Unsupported server type")
+
+ + + + +
+
+ +
+ + def + write(self, *args, **kwargs): + + + +
+ +
306    def write(self, *args, **kwargs):
+307        return self._writer.write(*args, **kwargs)
+
+ + + + +
+
+ +
+ + def + release(self, *args, **kwargs): + + + +
+ +
309    def release(self, *args, **kwargs):
+310        return self._writer.release(*args, **kwargs)
+
+ + + + +
+
+ +
+ + def + spec(self, *args, **kwargs): + + + +
+ +
312    def spec(self, *args, **kwargs):
+313        return self._writer.spec(*args, **kwargs)
+
+ + + + +
+
+
+ +
+ + class + VideoWriter_fourcc: + + + +
+ +
421class VideoWriter_fourcc:
+422    def __init__(self, *args):
+423        self._args = args
+
+ + + + +
+ +
+ + VideoWriter_fourcc(*args) + + + +
+ +
422    def __init__(self, *args):
+423        self._args = args
+
+ + + + +
+
+
+ +
+ + def + frameify(obj, field_name=None): + + + +
+ +
426def frameify(obj, field_name=None):
+427    """
+428    Turn an object (e.g., ndarray) into a Frame.
+429    """
+430
+431    if isinstance(obj, Frame):
+432        return obj
+433    elif isinstance(obj, np.ndarray):
+434        return _inline_frame(obj)
+435    else:
+436        if field_name is not None:
+437            raise Exception(
+438                f"Unsupported type for field {field_name}, expected Frame or np.ndarray"
+439            )
+440        else:
+441            raise Exception("Unsupported type, expected Frame or np.ndarray")
+
+ + +

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

+
+ + +
+
+ +
+ + def + imread(path, *args): + + + +
+ +
444def imread(path, *args):
+445    if len(args) > 0:
+446        raise NotImplementedError("imread does not support additional arguments")
+447
+448    assert path.lower().endswith((".jpg", ".jpeg", ".png"))
+449    server = _server()
+450    source = vf.Source(server, str(uuid.uuid4()), path, 0)
+451    frame = Frame(source.iloc[0], source.fmt())
+452    return frame
+
+ + + + +
+
+ +
+ + def + imwrite(path, img, *args): + + + +
+ +
455def imwrite(path, img, *args):
+456    if len(args) > 0:
+457        raise NotImplementedError("imwrite does not support additional arguments")
+458
+459    img = frameify(img)
+460
+461    fmt = img._fmt.copy()
+462    width = fmt["width"]
+463    height = fmt["height"]
+464    f = img._f
+465
+466    domain = [Fraction(0, 1)]
+467
+468    if path.lower().endswith(".png"):
+469        img._mut()  # Make sure it's in rgb24
+470        spec = vf.Spec(
+471            domain,
+472            lambda t, i: img._f,
+473            {"width": width, "height": height, "pix_fmt": "rgb24"},
+474        )
+475        spec.save(_server(), path, encoder="png")
+476    elif path.lower().endswith((".jpg", ".jpeg")):
+477        if img._modified:
+478            # it's rgb24, we need to convert to something jpeg can handle
+479            f = _filter_scale(img._f, pix_fmt="yuv420p")
+480            fmt["pix_fmt"] = "yuv420p"
+481        else:
+482            if fmt["pix_fmt"] not in ["yuvj420p", "yuvj422p", "yuvj444p"]:
+483                f = _filter_scale(img._f, pix_fmt="yuvj420p")
+484                fmt["pix_fmt"] = "yuvj420p"
+485
+486        spec = vf.Spec(domain, lambda t, i: f, fmt)
+487        spec.save(_server(), path, encoder="mjpeg")
+488    else:
+489        raise Exception("Unsupported image format")
+
+ + + + +
+
+ +
+ + def + vidplay(video, *args, **kwargs): + + + +
+ +
492def vidplay(video, *args, **kwargs):
+493    """
+494    Play a vidformer video specification.
+495
+496    Args:
+497        video: one of [vidformer.Spec, vidformer.Source, vidformer.cv2.VideoWriter]
+498    """
+499
+500    if isinstance(video, vf.Spec):
+501        return video.play(_server(), *args, **kwargs)
+502    elif isinstance(video, vf.Source):
+503        return video.play(_server(), *args, **kwargs)
+504    elif isinstance(video, VideoWriter):
+505        return video.spec().play(_server(), *args, **kwargs)
+506    elif isinstance(video, igni.IgniSpec):
+507        return video.play(*args, **kwargs)
+508    else:
+509        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): + + + +
+ +
512def rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):
+513    """
+514    cv.rectangle(	img, pt1, pt2, color[, thickness[, lineType[, shift]]]	)
+515    """
+516
+517    img = frameify(img)
+518    img._mut()
+519
+520    assert len(pt1) == 2
+521    assert len(pt2) == 2
+522    assert all(isinstance(x, int) for x in pt1)
+523    assert all(isinstance(x, int) for x in pt2)
+524
+525    assert len(color) == 3 or len(color) == 4
+526    color = [float(x) for x in color]
+527    if len(color) == 3:
+528        color.append(255.0)
+529
+530    args = []
+531    if thickness is not None:
+532        assert isinstance(thickness, int)
+533        args.append(thickness)
+534    if lineType is not None:
+535        assert isinstance(lineType, int)
+536        assert thickness is not None
+537        args.append(lineType)
+538    if shift is not None:
+539        assert isinstance(shift, int)
+540        assert shift is not None
+541        args.append(shift)
+542
+543    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): + + + +
+ +
546def putText(
+547    img,
+548    text,
+549    org,
+550    fontFace,
+551    fontScale,
+552    color,
+553    thickness=None,
+554    lineType=None,
+555    bottomLeftOrigin=None,
+556):
+557    """
+558    cv.putText(	img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]	)
+559    """
+560
+561    img = frameify(img)
+562    img._mut()
+563
+564    assert isinstance(text, str)
+565
+566    assert len(org) == 2
+567    assert all(isinstance(x, int) for x in org)
+568
+569    assert isinstance(fontFace, int)
+570    assert isinstance(fontScale, float) or isinstance(fontScale, int)
+571    fontScale = float(fontScale)
+572
+573    assert len(color) == 3 or len(color) == 4
+574    color = [float(x) for x in color]
+575    if len(color) == 3:
+576        color.append(255.0)
+577
+578    args = []
+579    if thickness is not None:
+580        assert isinstance(thickness, int)
+581        args.append(thickness)
+582    if lineType is not None:
+583        assert isinstance(lineType, int)
+584        assert thickness is not None
+585        args.append(lineType)
+586    if bottomLeftOrigin is not None:
+587        assert isinstance(bottomLeftOrigin, bool)
+588        assert lineType is not None
+589        args.append(bottomLeftOrigin)
+590
+591    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): + + + +
+ +
594def arrowedLine(
+595    img, pt1, pt2, color, thickness=None, line_type=None, shift=None, tipLength=None
+596):
+597    """
+598    cv.arrowedLine(	img, pt1, pt2, color[, thickness[, line_type[, shift[, tipLength]]]]	)
+599    """
+600    img = frameify(img)
+601    img._mut()
+602
+603    assert len(pt1) == 2
+604    assert len(pt2) == 2
+605    assert all(isinstance(x, int) for x in pt1)
+606    assert all(isinstance(x, int) for x in pt2)
+607
+608    assert len(color) == 3 or len(color) == 4
+609    color = [float(x) for x in color]
+610    if len(color) == 3:
+611        color.append(255.0)
+612
+613    args = []
+614    if thickness is not None:
+615        assert isinstance(thickness, int)
+616        args.append(thickness)
+617    if line_type is not None:
+618        assert isinstance(line_type, int)
+619        assert thickness is not None
+620        args.append(line_type)
+621    if shift is not None:
+622        assert isinstance(shift, int)
+623        assert shift is not None
+624        args.append(shift)
+625    if tipLength is not None:
+626        assert isinstance(tipLength, float)
+627        assert shift is not None
+628        args.append(tipLength)
+629
+630    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): + + + +
+ +
633def line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):
+634    img = frameify(img)
+635    img._mut()
+636
+637    assert len(pt1) == 2
+638    assert len(pt2) == 2
+639    assert all(isinstance(x, int) for x in pt1)
+640    assert all(isinstance(x, int) for x in pt2)
+641
+642    assert len(color) == 3 or len(color) == 4
+643    color = [float(x) for x in color]
+644    if len(color) == 3:
+645        color.append(255.0)
+646
+647    args = []
+648    if thickness is not None:
+649        assert isinstance(thickness, int)
+650        args.append(thickness)
+651    if lineType is not None:
+652        assert isinstance(lineType, int)
+653        assert thickness is not None
+654        args.append(lineType)
+655    if shift is not None:
+656        assert isinstance(shift, int)
+657        assert shift is not None
+658        args.append(shift)
+659
+660    img._f = _filter_line(img._f, pt1, pt2, color, *args)
+
+ + + + +
+
+ +
+ + def + circle( img, center, radius, color, thickness=None, lineType=None, shift=None): + + + +
+ +
663def circle(img, center, radius, color, thickness=None, lineType=None, shift=None):
+664    img = frameify(img)
+665    img._mut()
+666
+667    assert len(center) == 2
+668    assert all(isinstance(x, int) for x in center)
+669
+670    assert isinstance(radius, int)
+671
+672    assert len(color) == 3 or len(color) == 4
+673    color = [float(x) for x in color]
+674    if len(color) == 3:
+675        color.append(255.0)
+676
+677    args = []
+678    if thickness is not None:
+679        assert isinstance(thickness, int)
+680        args.append(thickness)
+681    if lineType is not None:
+682        assert isinstance(lineType, int)
+683        assert thickness is not None
+684        args.append(lineType)
+685    if shift is not None:
+686        assert isinstance(shift, int)
+687        assert shift is not None
+688        args.append(shift)
+689
+690    img._f = _filter_circle(img._f, center, radius, color, *args)
+
+ + + + +
+
+ +
+ + def + getFontScaleFromHeight(*args, **kwargs): + + + +
+ +
693def getFontScaleFromHeight(*args, **kwargs):
+694    """
+695    cv.getFontScaleFromHeight(	fontFace, pixelHeight[, thickness]	)
+696    """
+697    if _opencv2 is None:
+698        raise NotImplementedError("getFontScaleFromHeight requires the cv2 module")
+699    return _opencv2.getFontScaleFromHeight(*args, **kwargs)
+
+ + +

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

+
+ + +
+
+ +
+ + def + getTextSize(*args, **kwargs): + + + +
+ +
702def getTextSize(*args, **kwargs):
+703    """
+704    cv.getTextSize(	text, fontFace, fontScale, thickness	)
+705    """
+706    if _opencv2 is None:
+707        raise NotImplementedError("getTextSize requires the cv2 module")
+708    return _opencv2.getTextSize(*args, **kwargs)
+
+ + +

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

+
+ + +
+
+ +
+ + def + addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=-1): + + + +
+ +
711def addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=-1):
+712    """
+713    cv.addWeighted(	src1, alpha, src2, beta, gamma[, dst[, dtype]]	) -> 	dst
+714    """
+715    src1 = frameify(src1, "src1")
+716    src2 = frameify(src2, "src2")
+717    src1._mut()
+718    src2._mut()
+719
+720    if dst is None:
+721        dst = Frame(src1._f, src1._fmt.copy())
+722    else:
+723        assert isinstance(dst, Frame), "dst must be a Frame"
+724    dst._mut()
+725
+726    assert isinstance(alpha, float) or isinstance(alpha, int)
+727    assert isinstance(beta, float) or isinstance(beta, int)
+728    assert isinstance(gamma, float) or isinstance(gamma, int)
+729    alpha = float(alpha)
+730    beta = float(beta)
+731    gamma = float(gamma)
+732
+733    if dtype != -1:
+734        raise Exception("addWeighted does not support the dtype argument")
+735
+736    dst._f = _filter_addWeighted(src1._f, alpha, src2._f, beta, gamma)
+737    return dst
+
+ + +

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

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

Play the video live in the notebook.

+
+ + +
+
+ +
+ + def + load(self, server): + + + +
+ +
314    def load(self, server):
+315        spec, sources, filters = self._to_json_spec()
+316        spec_json_bytes = json.dumps(spec).encode("utf-8")
+317        spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
+318        spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
+319
+320        sources = [
+321            {
+322                "name": s._name,
+323                "path": s._path,
+324                "stream": s._stream,
+325                "service": s._service.as_json() if s._service is not None else None,
+326            }
+327            for s in sources
+328        ]
+329        filters = {
+330            k: {
+331                "filter": v._func,
+332                "args": v._kwargs,
+333            }
+334            for k, v in filters.items()
+335        }
+336        arrays = []
+337
+338        resp = server._new(spec_obj_json_gzip_b64, sources, filters, arrays, self._fmt)
+339        namespace = resp["namespace"]
+340        return Loader(server, namespace, self._domain)
+
+ + + + +
+
+ +
+ + def + save(self, server, pth, encoder=None, encoder_opts=None, format=None): + + + +
+ +
342    def save(self, server, pth, encoder=None, encoder_opts=None, format=None):
+343        """Save the video to a file."""
+344
+345        assert encoder is None or type(encoder) == str
+346        assert encoder_opts is None or type(encoder_opts) == dict
+347        if encoder_opts is not None:
+348            for k, v in encoder_opts.items():
+349                assert type(k) == str and type(v) == str
+350
+351        spec, sources, filters = self._to_json_spec()
+352        spec_json_bytes = json.dumps(spec).encode("utf-8")
+353        spec_obj_json_gzip = gzip.compress(spec_json_bytes, compresslevel=1)
+354        spec_obj_json_gzip_b64 = base64.b64encode(spec_obj_json_gzip).decode("utf-8")
+355
+356        sources = [
+357            {
+358                "name": s._name,
+359                "path": s._path,
+360                "stream": s._stream,
+361                "service": s._service.as_json() if s._service is not None else None,
+362            }
+363            for s in sources
+364        ]
+365        filters = {
+366            k: {
+367                "filter": v._func,
+368                "args": v._kwargs,
+369            }
+370            for k, v in filters.items()
+371        }
+372        arrays = []
+373
+374        resp = server._export(
+375            pth,
+376            spec_obj_json_gzip_b64,
+377            sources,
+378            filters,
+379            arrays,
+380            self._fmt,
+381            encoder,
+382            encoder_opts,
+383            format,
+384        )
+385
+386        return resp
+
+ + +

Save the video to a file.

+
+ + +
+
+
+ +
+ + class + Loader: + + + +
+ +
466class Loader:
+467    def __init__(self, server, namespace: str, domain):
+468        self._server = server
+469        self._namespace = namespace
+470        self._domain = domain
+471
+472    def _chunk(self, start_i, end_i):
+473        return self._server._raw(self._namespace, start_i, end_i)
+474
+475    def __len__(self):
+476        return len(self._domain)
+477
+478    def _find_index_by_rational(self, value):
+479        if value not in self._domain:
+480            raise ValueError(f"Rational timestamp {value} is not in the domain")
+481        return self._domain.index(value)
+482
+483    def __getitem__(self, index):
+484        if isinstance(index, slice):
+485            start = index.start if index.start is not None else 0
+486            end = index.stop if index.stop is not None else len(self._domain)
+487            assert start >= 0 and start < len(self._domain)
+488            assert end >= 0 and end <= len(self._domain)
+489            assert start <= end
+490            num_frames = end - start
+491            all_bytes = self._chunk(start, end - 1)
+492            all_bytes_len = len(all_bytes)
+493            assert all_bytes_len % num_frames == 0
+494            return [
+495                all_bytes[
+496                    i
+497                    * all_bytes_len
+498                    // num_frames : (i + 1)
+499                    * all_bytes_len
+500                    // num_frames
+501                ]
+502                for i in range(num_frames)
+503            ]
+504        elif isinstance(index, int):
+505            assert index >= 0 and index < len(self._domain)
+506            return self._chunk(index, index)
+507        else:
+508            raise TypeError(
+509                "Invalid argument type for iloc. Use a slice or an integer."
+510            )
+
+ + + + +
+ +
+ + Loader(server, namespace: str, domain) + + + +
+ +
467    def __init__(self, server, namespace: str, domain):
+468        self._server = server
+469        self._namespace = namespace
+470        self._domain = domain
+
+ + + + +
+
+
+ +
+ + class + YrdenServer: + + + +
+ +
513class YrdenServer:
+514    """
+515    A connection to a Yrden server.
+516
+517    A yrden server is the main API for local use of vidformer.
+518    """
+519
+520    def __init__(self, domain=None, port=None, bin=None, hls_prefix=None):
+521        """
+522        Connect to a Yrden server
+523
+524        Can either connect to an existing server, if domain and port are provided, or start a new server using the provided binary.
+525        If no domain or binary is provided, the `VIDFORMER_BIN` environment variable is used.
+526        """
+527
+528        self._domain = domain
+529        self._port = port
+530        self._proc = None
+531        if self._port is None:
+532            if bin is None:
+533                if os.getenv("VIDFORMER_BIN") is not None:
+534                    bin = os.getenv("VIDFORMER_BIN")
+535                else:
+536                    bin = "vidformer-cli"
+537
+538            self._domain = "localhost"
+539            self._port = random.randint(49152, 65535)
+540            cmd = [bin, "yrden", "--port", str(self._port)]
+541            if _in_notebook:
+542                # We need to print the URL in the notebook
+543                # This is a trick to get VS Code to forward the port
+544                cmd += ["--print-url"]
+545
+546            if hls_prefix is not None:
+547                if not type(hls_prefix) == str:
+548                    raise Exception("hls_prefix must be a string")
+549                cmd += ["--hls-prefix", hls_prefix]
+550
+551            self._proc = subprocess.Popen(cmd)
+552
+553        version = _check_hls_link_exists(f"http://{self._domain}:{self._port}/")
+554        if version is None:
+555            raise Exception("Failed to connect to server")
+556
+557        expected_version = f"vidformer-yrden v{__version__}"
+558        if version != expected_version:
+559            print(
+560                f"Warning: Expected version `{expected_version}`, got `{version}`. API may not be compatible!"
+561            )
+562
+563    def _source(self, name: str, path: str, stream: int, service):
+564        r = requests.post(
+565            f"http://{self._domain}:{self._port}/source",
+566            json={
+567                "name": name,
+568                "path": path,
+569                "stream": stream,
+570                "service": service.as_json() if service is not None else None,
+571            },
+572        )
+573        if not r.ok:
+574            raise Exception(r.text)
+575
+576        resp = r.json()
+577        resp["ts"] = [Fraction(x[0], x[1]) for x in resp["ts"]]
+578        return resp
+579
+580    def _new(self, spec, sources, filters, arrays, fmt):
+581        req = {
+582            "spec": spec,
+583            "sources": sources,
+584            "filters": filters,
+585            "arrays": arrays,
+586            "width": fmt["width"],
+587            "height": fmt["height"],
+588            "pix_fmt": fmt["pix_fmt"],
+589        }
+590
+591        r = requests.post(f"http://{self._domain}:{self._port}/new", json=req)
+592        if not r.ok:
+593            raise Exception(r.text)
+594
+595        return r.json()
+596
+597    def _export(
+598        self, pth, spec, sources, filters, arrays, fmt, encoder, encoder_opts, format
+599    ):
+600        req = {
+601            "spec": spec,
+602            "sources": sources,
+603            "filters": filters,
+604            "arrays": arrays,
+605            "width": fmt["width"],
+606            "height": fmt["height"],
+607            "pix_fmt": fmt["pix_fmt"],
+608            "output_path": pth,
+609            "encoder": encoder,
+610            "encoder_opts": encoder_opts,
+611            "format": format,
+612        }
+613
+614        r = requests.post(f"http://{self._domain}:{self._port}/export", json=req)
+615        if not r.ok:
+616            raise Exception(r.text)
+617
+618        return r.json()
+619
+620    def _raw(self, namespace, start_i, end_i):
+621        r = requests.get(
+622            f"http://{self._domain}:{self._port}/{namespace}/raw/{start_i}-{end_i}"
+623        )
+624        if not r.ok:
+625            raise Exception(r.text)
+626        return r.content
+627
+628    def hls_js_url(self):
+629        """Return the link to the yrden-hosted hls.js file"""
+630        return f"http://{self._domain}:{self._port}/hls.js"
+631
+632    def __del__(self):
+633        if self._proc is not None:
+634            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) + + + +
+ +
520    def __init__(self, domain=None, port=None, bin=None, hls_prefix=None):
+521        """
+522        Connect to a Yrden server
+523
+524        Can either connect to an existing server, if domain and port are provided, or start a new server using the provided binary.
+525        If no domain or binary is provided, the `VIDFORMER_BIN` environment variable is used.
+526        """
+527
+528        self._domain = domain
+529        self._port = port
+530        self._proc = None
+531        if self._port is None:
+532            if bin is None:
+533                if os.getenv("VIDFORMER_BIN") is not None:
+534                    bin = os.getenv("VIDFORMER_BIN")
+535                else:
+536                    bin = "vidformer-cli"
+537
+538            self._domain = "localhost"
+539            self._port = random.randint(49152, 65535)
+540            cmd = [bin, "yrden", "--port", str(self._port)]
+541            if _in_notebook:
+542                # We need to print the URL in the notebook
+543                # This is a trick to get VS Code to forward the port
+544                cmd += ["--print-url"]
+545
+546            if hls_prefix is not None:
+547                if not type(hls_prefix) == str:
+548                    raise Exception("hls_prefix must be a string")
+549                cmd += ["--hls-prefix", hls_prefix]
+550
+551            self._proc = subprocess.Popen(cmd)
+552
+553        version = _check_hls_link_exists(f"http://{self._domain}:{self._port}/")
+554        if version is None:
+555            raise Exception("Failed to connect to server")
+556
+557        expected_version = f"vidformer-yrden v{__version__}"
+558        if version != expected_version:
+559            print(
+560                f"Warning: Expected version `{expected_version}`, got `{version}`. API may not be compatible!"
+561            )
+
+ + +

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): + + + +
+ +
628    def hls_js_url(self):
+629        """Return the link to the yrden-hosted hls.js file"""
+630        return f"http://{self._domain}:{self._port}/hls.js"
+
+ + +

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

+
+ + +
+
+
+ +
+ + class + SourceExpr: + + + +
+ +
637class SourceExpr:
+638    def __init__(self, source, idx, is_iloc):
+639        self._source = source
+640        self._idx = idx
+641        self._is_iloc = is_iloc
+642
+643    def __repr__(self):
+644        if self._is_iloc:
+645            return f"{self._source._name}.iloc[{self._idx}]"
+646        else:
+647            return f"{self._source._name}[{self._idx}]"
+648
+649    def _to_json_spec(self):
+650        if self._is_iloc:
+651            return {
+652                "Source": {
+653                    "video": self._source._name,
+654                    "index": {"ILoc": int(self._idx)},
+655                }
+656            }
+657        else:
+658            return {
+659                "Source": {
+660                    "video": self._source._name,
+661                    "index": {"T": [self._idx.numerator, self._idx.denominator]},
+662                }
+663            }
+664
+665    def _sources(self):
+666        return set([self._source])
+667
+668    def _filters(self):
+669        return {}
+
+ + + + +
+ +
+ + SourceExpr(source, idx, is_iloc) + + + +
+ +
638    def __init__(self, source, idx, is_iloc):
+639        self._source = source
+640        self._idx = idx
+641        self._is_iloc = is_iloc
+
+ + + + +
+
+
+ +
+ + class + SourceILoc: + + + +
+ +
672class SourceILoc:
+673    def __init__(self, source):
+674        self._source = source
+675
+676    def __getitem__(self, idx):
+677        if type(idx) != int:
+678            raise Exception(f"Source iloc index must be an integer, got a {type(idx)}")
+679        return SourceExpr(self._source, idx, True)
+
+ + + + +
+ +
+ + SourceILoc(source) + + + +
+ +
673    def __init__(self, source):
+674        self._source = source
+
+ + + + +
+
+
+ +
+ + class + Source: + + + +
+ +
682class Source:
+683    """A video source."""
+684
+685    def __init__(
+686        self, server: YrdenServer, name: str, path: str, stream: int, service=None
+687    ):
+688        if service is None:
+689            # check if path is a http URL and, if so, automatically set the service
+690            # for example, the following code should work with just vf.Source(server, "tos_720p", "https://f.dominik.win/data/dve2/tos_720p.mp4")
+691            # this creates a storage service with endpoint "https://f.dominik.win/" and path "data/dve2/tos_720p.mp4"
+692            # don't use the root parameter in this case
+693
+694            match = re.match(r"(http|https)://([^/]+)(.*)", path)
+695            if match is not None:
+696                endpoint = f"{match.group(1)}://{match.group(2)}"
+697                path = match.group(3)
+698                # remove leading slash
+699                if path.startswith("/"):
+700                    path = path[1:]
+701                service = StorageService("http", endpoint=endpoint)
+702
+703        self._server = server
+704        self._name = name
+705        self._path = path
+706        self._stream = stream
+707        self._service = service
+708
+709        self.iloc = SourceILoc(self)
+710
+711        self._src = self._server._source(
+712            self._name, self._path, self._stream, self._service
+713        )
+714
+715    def fmt(self):
+716        return {
+717            "width": self._src["width"],
+718            "height": self._src["height"],
+719            "pix_fmt": self._src["pix_fmt"],
+720        }
+721
+722    def ts(self):
+723        return self._src["ts"]
+724
+725    def __len__(self):
+726        return len(self._src["ts"])
+727
+728    def __getitem__(self, idx):
+729        if type(idx) != Fraction:
+730            raise Exception("Source index must be a Fraction")
+731        return SourceExpr(self, idx, False)
+732
+733    def play(self, *args, **kwargs):
+734        """Play the video live in the notebook."""
+735
+736        domain = self.ts()
+737        render = lambda t, i: self[t]
+738        spec = Spec(domain, render, self.fmt())
+739        return spec.play(*args, **kwargs)
+
+ + +

A video source.

+
+ + +
+ +
+ + Source( server: YrdenServer, name: str, path: str, stream: int, service=None) + + + +
+ +
685    def __init__(
+686        self, server: YrdenServer, name: str, path: str, stream: int, service=None
+687    ):
+688        if service is None:
+689            # check if path is a http URL and, if so, automatically set the service
+690            # for example, the following code should work with just vf.Source(server, "tos_720p", "https://f.dominik.win/data/dve2/tos_720p.mp4")
+691            # this creates a storage service with endpoint "https://f.dominik.win/" and path "data/dve2/tos_720p.mp4"
+692            # don't use the root parameter in this case
+693
+694            match = re.match(r"(http|https)://([^/]+)(.*)", path)
+695            if match is not None:
+696                endpoint = f"{match.group(1)}://{match.group(2)}"
+697                path = match.group(3)
+698                # remove leading slash
+699                if path.startswith("/"):
+700                    path = path[1:]
+701                service = StorageService("http", endpoint=endpoint)
+702
+703        self._server = server
+704        self._name = name
+705        self._path = path
+706        self._stream = stream
+707        self._service = service
+708
+709        self.iloc = SourceILoc(self)
+710
+711        self._src = self._server._source(
+712            self._name, self._path, self._stream, self._service
+713        )
+
+ + + + +
+
+
+ iloc + + +
+ + + + +
+
+ +
+ + def + fmt(self): + + + +
+ +
715    def fmt(self):
+716        return {
+717            "width": self._src["width"],
+718            "height": self._src["height"],
+719            "pix_fmt": self._src["pix_fmt"],
+720        }
+
+ + + + +
+
+ +
+ + def + ts(self): + + + +
+ +
722    def ts(self):
+723        return self._src["ts"]
+
+ + + + +
+
+ +
+ + def + play(self, *args, **kwargs): + + + +
+ +
733    def play(self, *args, **kwargs):
+734        """Play the video live in the notebook."""
+735
+736        domain = self.ts()
+737        render = lambda t, i: self[t]
+738        spec = Spec(domain, render, self.fmt())
+739        return spec.play(*args, **kwargs)
+
+ + +

Play the video live in the notebook.

+
+ + +
+
+
+ +
+ + class + StorageService: + + + +
+ +
742class StorageService:
+743    def __init__(self, service: str, **kwargs):
+744        if type(service) != str:
+745            raise Exception("Service name must be a string")
+746        self._service = service
+747        for k, v in kwargs.items():
+748            if type(v) != str:
+749                raise Exception(f"Value of {k} must be a string")
+750        self._config = kwargs
+751
+752    def as_json(self):
+753        return {"service": self._service, "config": self._config}
+754
+755    def __repr__(self):
+756        return f"{self._service}(config={self._config})"
+
+ + + + +
+ +
+ + StorageService(service: str, **kwargs) + + + +
+ +
743    def __init__(self, service: str, **kwargs):
+744        if type(service) != str:
+745            raise Exception("Service name must be a string")
+746        self._service = service
+747        for k, v in kwargs.items():
+748            if type(v) != str:
+749                raise Exception(f"Value of {k} must be a string")
+750        self._config = kwargs
+
+ + + + +
+
+ +
+ + def + as_json(self): + + + +
+ +
752    def as_json(self):
+753        return {"service": self._service, "config": self._config}
+
+ + + + +
+
+
+ +
+ + class + Filter: + + + +
+ +
791class Filter:
+792    """A video filter."""
+793
+794    def __init__(self, name: str, tl_func=None, **kwargs):
+795        self._name = name
+796
+797        # tl_func is the top level func, which is the true implementation, not just a pretty name
+798        if tl_func is None:
+799            self._func = name
+800        else:
+801            self._func = tl_func
+802
+803        # filter infra args, not invocation args
+804        for k, v in kwargs.items():
+805            if type(v) != str:
+806                raise Exception(f"Value of {k} must be a string")
+807        self._kwargs = kwargs
+808
+809    def __call__(self, *args, **kwargs):
+810        return FilterExpr(self, args, kwargs)
+
+ + +

A video filter.

+
+ + +
+ +
+ + Filter(name: str, tl_func=None, **kwargs) + + + +
+ +
794    def __init__(self, name: str, tl_func=None, **kwargs):
+795        self._name = name
+796
+797        # tl_func is the top level func, which is the true implementation, not just a pretty name
+798        if tl_func is None:
+799            self._func = name
+800        else:
+801            self._func = tl_func
+802
+803        # filter infra args, not invocation args
+804        for k, v in kwargs.items():
+805            if type(v) != str:
+806                raise Exception(f"Value of {k} must be a string")
+807        self._kwargs = kwargs
+
+ + + + +
+
+
+ +
+ + class + FilterExpr: + + + +
+ +
813class FilterExpr:
+814    def __init__(self, filter: Filter, args, kwargs):
+815        self._filter = filter
+816        self._args = args
+817        self._kwargs = kwargs
+818
+819    def __repr__(self):
+820        args = []
+821        for arg in self._args:
+822            val = f'"{arg}"' if type(arg) == str else str(arg)
+823            args.append(str(val))
+824        for k, v in self._kwargs.items():
+825            val = f'"{v}"' if type(v) == str else str(v)
+826            args.append(f"{k}={val}")
+827        return f"{self._filter._name}({', '.join(args)})"
+828
+829    def _to_json_spec(self):
+830        args = []
+831        for arg in self._args:
+832            args.append(_json_arg(arg))
+833        kwargs = {}
+834        for k, v in self._kwargs.items():
+835            kwargs[k] = _json_arg(v)
+836        return {"Filter": {"name": self._filter._name, "args": args, "kwargs": kwargs}}
+837
+838    def _sources(self):
+839        s = set()
+840        for arg in self._args:
+841            if type(arg) == FilterExpr or type(arg) == SourceExpr:
+842                s = s.union(arg._sources())
+843        for arg in self._kwargs.values():
+844            if type(arg) == FilterExpr or type(arg) == SourceExpr:
+845                s = s.union(arg._sources())
+846        return s
+847
+848    def _filters(self):
+849        f = {self._filter._name: self._filter}
+850        for arg in self._args:
+851            if type(arg) == FilterExpr:
+852                f = {**f, **arg._filters()}
+853        for arg in self._kwargs.values():
+854            if type(arg) == FilterExpr:
+855                f = {**f, **arg._filters()}
+856        return f
+
+ + + + +
+ +
+ + FilterExpr(filter: Filter, args, kwargs) + + + +
+ +
814    def __init__(self, filter: Filter, args, kwargs):
+815        self._filter = filter
+816        self._args = args
+817        self._kwargs = kwargs
+
+ + + + +
+
+
+ +
+ + class + UDF: + + + +
+ +
 859class UDF:
+ 860    """User-defined filter superclass"""
+ 861
+ 862    def __init__(self, name: str):
+ 863        self._name = name
+ 864        self._socket_path = None
+ 865        self._p = None
+ 866
+ 867    def filter(self, *args, **kwargs):
+ 868        raise Exception("User must implement the filter method")
+ 869
+ 870    def filter_type(self, *args, **kwargs):
+ 871        raise Exception("User must implement the filter_type method")
+ 872
+ 873    def into_filter(self):
+ 874        assert self._socket_path is None
+ 875        self._socket_path = f"/tmp/vidformer-{self._name}-{str(uuid.uuid4())}.sock"
+ 876        self._p = multiprocessing.Process(
+ 877            target=_run_udf_host, args=(self, self._socket_path)
+ 878        )
+ 879        self._p.start()
+ 880        return Filter(
+ 881            name=self._name, tl_func="IPC", socket=self._socket_path, func=self._name
+ 882        )
+ 883
+ 884    def _handle_connection(self, connection):
+ 885        try:
+ 886            while True:
+ 887                frame_len = connection.recv(4)
+ 888                if not frame_len or len(frame_len) != 4:
+ 889                    break
+ 890                frame_len = int.from_bytes(frame_len, byteorder="big")
+ 891                data = connection.recv(frame_len)
+ 892                if not data:
+ 893                    break
+ 894
+ 895                while len(data) < frame_len:
+ 896                    new_data = connection.recv(frame_len - len(data))
+ 897                    if not new_data:
+ 898                        raise Exception("Partial data received")
+ 899                    data += new_data
+ 900
+ 901                obj = msgpack.unpackb(data, raw=False)
+ 902                f_func, f_op, f_args, f_kwargs = (
+ 903                    obj["func"],
+ 904                    obj["op"],
+ 905                    obj["args"],
+ 906                    obj["kwargs"],
+ 907                )
+ 908
+ 909                response = None
+ 910                if f_op == "filter":
+ 911                    f_args = [self._deser_filter(x) for x in f_args]
+ 912                    f_kwargs = {k: self._deser_filter(v) for k, v in f_kwargs}
+ 913                    response = self.filter(*f_args, **f_kwargs)
+ 914                    if type(response) != UDFFrame:
+ 915                        raise Exception(
+ 916                            f"filter must return a UDFFrame, got {type(response)}"
+ 917                        )
+ 918                    if response.frame_type().pix_fmt() != "rgb24":
+ 919                        raise Exception(
+ 920                            f"filter must return a frame with pix_fmt 'rgb24', got {response.frame_type().pix_fmt()}"
+ 921                        )
+ 922
+ 923                    response = response._response_ser()
+ 924                elif f_op == "filter_type":
+ 925                    f_args = [self._deser_filter_type(x) for x in f_args]
+ 926                    f_kwargs = {k: self._deser_filter_type(v) for k, v in f_kwargs}
+ 927                    response = self.filter_type(*f_args, **f_kwargs)
+ 928                    if type(response) != UDFFrameType:
+ 929                        raise Exception(
+ 930                            f"filter_type must return a UDFFrameType, got {type(response)}"
+ 931                        )
+ 932                    if response.pix_fmt() != "rgb24":
+ 933                        raise Exception(
+ 934                            f"filter_type must return a frame with pix_fmt 'rgb24', got {response.pix_fmt()}"
+ 935                        )
+ 936                    response = response._response_ser()
+ 937                else:
+ 938                    raise Exception(f"Unknown operation: {f_op}")
+ 939
+ 940                response = msgpack.packb(response, use_bin_type=True)
+ 941                response_len = len(response).to_bytes(4, byteorder="big")
+ 942                connection.sendall(response_len)
+ 943                connection.sendall(response)
+ 944        finally:
+ 945            connection.close()
+ 946
+ 947    def _deser_filter_type(self, obj):
+ 948        assert type(obj) == dict
+ 949        keys = list(obj.keys())
+ 950        assert len(keys) == 1
+ 951        type_key = keys[0]
+ 952        assert type_key in ["FrameType", "String", "Int", "Bool"]
+ 953
+ 954        if type_key == "FrameType":
+ 955            frame = obj[type_key]
+ 956            assert type(frame) == dict
+ 957            assert "width" in frame
+ 958            assert "height" in frame
+ 959            assert "format" in frame
+ 960            assert type(frame["width"]) == int
+ 961            assert type(frame["height"]) == int
+ 962            assert frame["format"] == 2  # AV_PIX_FMT_RGB24
+ 963            return UDFFrameType(frame["width"], frame["height"], "rgb24")
+ 964        elif type_key == "String":
+ 965            assert type(obj[type_key]) == str
+ 966            return obj[type_key]
+ 967        elif type_key == "Int":
+ 968            assert type(obj[type_key]) == int
+ 969            return obj[type_key]
+ 970        elif type_key == "Bool":
+ 971            assert type(obj[type_key]) == bool
+ 972            return obj[type_key]
+ 973        else:
+ 974            assert False, f"Unknown type: {type_key}"
+ 975
+ 976    def _deser_filter(self, obj):
+ 977        assert type(obj) == dict
+ 978        keys = list(obj.keys())
+ 979        assert len(keys) == 1
+ 980        type_key = keys[0]
+ 981        assert type_key in ["Frame", "String", "Int", "Bool"]
+ 982
+ 983        if type_key == "Frame":
+ 984            frame = obj[type_key]
+ 985            assert type(frame) == dict
+ 986            assert "data" in frame
+ 987            assert "width" in frame
+ 988            assert "height" in frame
+ 989            assert "format" in frame
+ 990            assert type(frame["width"]) == int
+ 991            assert type(frame["height"]) == int
+ 992            assert frame["format"] == "rgb24"
+ 993            assert type(frame["data"]) == bytes
+ 994
+ 995            data = np.frombuffer(frame["data"], dtype=np.uint8)
+ 996            data = data.reshape(frame["height"], frame["width"], 3)
+ 997            return UDFFrame(
+ 998                data, UDFFrameType(frame["width"], frame["height"], "rgb24")
+ 999            )
+1000        elif type_key == "String":
+1001            assert type(obj[type_key]) == str
+1002            return obj[type_key]
+1003        elif type_key == "Int":
+1004            assert type(obj[type_key]) == int
+1005            return obj[type_key]
+1006        elif type_key == "Bool":
+1007            assert type(obj[type_key]) == bool
+1008            return obj[type_key]
+1009        else:
+1010            assert False, f"Unknown type: {type_key}"
+1011
+1012    def _host(self, socket_path: str):
+1013        if os.path.exists(socket_path):
+1014            os.remove(socket_path)
+1015
+1016        # start listening on the socket
+1017        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+1018        sock.bind(socket_path)
+1019        sock.listen(1)
+1020
+1021        while True:
+1022            # accept incoming connection
+1023            connection, client_address = sock.accept()
+1024            thread = threading.Thread(
+1025                target=self._handle_connection, args=(connection,)
+1026            )
+1027            thread.start()
+1028
+1029    def __del__(self):
+1030        if self._socket_path is not None:
+1031            self._p.terminate()
+1032            if os.path.exists(self._socket_path):
+1033                # it's possible the process hasn't even created the socket yet
+1034                os.remove(self._socket_path)
+
+ + +

User-defined filter superclass

+
+ + +
+ +
+ + UDF(name: str) + + + +
+ +
862    def __init__(self, name: str):
+863        self._name = name
+864        self._socket_path = None
+865        self._p = None
+
+ + + + +
+
+ +
+ + def + filter(self, *args, **kwargs): + + + +
+ +
867    def filter(self, *args, **kwargs):
+868        raise Exception("User must implement the filter method")
+
+ + + + +
+
+ +
+ + def + filter_type(self, *args, **kwargs): + + + +
+ +
870    def filter_type(self, *args, **kwargs):
+871        raise Exception("User must implement the filter_type method")
+
+ + + + +
+
+ +
+ + def + into_filter(self): + + + +
+ +
873    def into_filter(self):
+874        assert self._socket_path is None
+875        self._socket_path = f"/tmp/vidformer-{self._name}-{str(uuid.uuid4())}.sock"
+876        self._p = multiprocessing.Process(
+877            target=_run_udf_host, args=(self, self._socket_path)
+878        )
+879        self._p.start()
+880        return Filter(
+881            name=self._name, tl_func="IPC", socket=self._socket_path, func=self._name
+882        )
+
+ + + + +
+
+
+ +
+ + class + UDFFrameType: + + + +
+ +
1037class UDFFrameType:
+1038    """
+1039    Frame type for use in UDFs.
+1040    """
+1041
+1042    def __init__(self, width: int, height: int, pix_fmt: str):
+1043        assert type(width) == int
+1044        assert type(height) == int
+1045        assert type(pix_fmt) == str
+1046
+1047        self._width = width
+1048        self._height = height
+1049        self._pix_fmt = pix_fmt
+1050
+1051    def width(self):
+1052        return self._width
+1053
+1054    def height(self):
+1055        return self._height
+1056
+1057    def pix_fmt(self):
+1058        return self._pix_fmt
+1059
+1060    def _response_ser(self):
+1061        return {
+1062            "frame_type": {
+1063                "width": self._width,
+1064                "height": self._height,
+1065                "format": 2,  # AV_PIX_FMT_RGB24
+1066            }
+1067        }
+1068
+1069    def __repr__(self):
+1070        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) + + + +
+ +
1042    def __init__(self, width: int, height: int, pix_fmt: str):
+1043        assert type(width) == int
+1044        assert type(height) == int
+1045        assert type(pix_fmt) == str
+1046
+1047        self._width = width
+1048        self._height = height
+1049        self._pix_fmt = pix_fmt
+
+ + + + +
+
+ +
+ + def + width(self): + + + +
+ +
1051    def width(self):
+1052        return self._width
+
+ + + + +
+
+ +
+ + def + height(self): + + + +
+ +
1054    def height(self):
+1055        return self._height
+
+ + + + +
+
+ +
+ + def + pix_fmt(self): + + + +
+ +
1057    def pix_fmt(self):
+1058        return self._pix_fmt
+
+ + + + +
+
+
+ +
+ + class + UDFFrame: + + + +
+ +
1073class UDFFrame:
+1074    """A symbolic reference to a frame for use in UDFs."""
+1075
+1076    def __init__(self, data: np.ndarray, f_type: UDFFrameType):
+1077        assert type(data) == np.ndarray
+1078        assert type(f_type) == UDFFrameType
+1079
+1080        # We only support RGB24 for now
+1081        assert data.dtype == np.uint8
+1082        assert data.shape[2] == 3
+1083
+1084        # check type matches
+1085        assert data.shape[0] == f_type.height()
+1086        assert data.shape[1] == f_type.width()
+1087        assert f_type.pix_fmt() == "rgb24"
+1088
+1089        self._data = data
+1090        self._f_type = f_type
+1091
+1092    def data(self):
+1093        return self._data
+1094
+1095    def frame_type(self):
+1096        return self._f_type
+1097
+1098    def _response_ser(self):
+1099        return {
+1100            "frame": {
+1101                "data": self._data.tobytes(),
+1102                "width": self._f_type.width(),
+1103                "height": self._f_type.height(),
+1104                "format": "rgb24",
+1105            }
+1106        }
+1107
+1108    def __repr__(self):
+1109        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) + + + +
+ +
1076    def __init__(self, data: np.ndarray, f_type: UDFFrameType):
+1077        assert type(data) == np.ndarray
+1078        assert type(f_type) == UDFFrameType
+1079
+1080        # We only support RGB24 for now
+1081        assert data.dtype == np.uint8
+1082        assert data.shape[2] == 3
+1083
+1084        # check type matches
+1085        assert data.shape[0] == f_type.height()
+1086        assert data.shape[1] == f_type.width()
+1087        assert f_type.pix_fmt() == "rgb24"
+1088
+1089        self._data = data
+1090        self._f_type = f_type
+
+ + + + +
+
+ +
+ + def + data(self): + + + +
+ +
1092    def data(self):
+1093        return self._data
+
+ + + + +
+
+ +
+ + def + frame_type(self): + + + +
+ +
1095    def frame_type(self):
+1096        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..c47e54a --- /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..050e8ed --- /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..3490628 --- /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..1a8d207 --- /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..e3fa78e --- /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..e5cfe6d --- /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 u8)

🔬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..584236a --- /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..38b084f --- /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..ffbb1d8 --- /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..bc5e07b --- /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..6cf2d7e --- /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..42431ac --- /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..6fa9413 --- /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..6a506a5 --- /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..03db8df --- /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..1ca8ac5 --- /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..921f74b --- /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..697ca10 --- /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..fa4d70b --- /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..e8170f6 --- /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..8fdd401 --- /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..7aa7943 --- /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..e161814 --- /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..c025481 --- /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..46e5ea1 --- /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..650c5bf --- /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..d084d60 --- /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..37c9b73 --- /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..8b47ff8 --- /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..ade20b6 --- /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..e5d1304 --- /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..66701ca --- /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..2220dc7 --- /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 u8)

🔬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..cbe35d5 --- /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..897a11c --- /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 u8)

🔬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..d3b7dbe --- /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 u8)

🔬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..bc1eec6 --- /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..5ddc933 --- /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..00404a9 --- /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..0098fd6 --- /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..dc4fad0 --- /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..7b8c0b9 --- /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..32b2308 --- /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..5869ef6 --- /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..b57bdb5 --- /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 u8)

🔬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..1e5a526 --- /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 u8)

🔬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..7d8692c --- /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 u8)

🔬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..0a79480 --- /dev/null +++ b/vidformer/sir/enum.FrameExpr.html @@ -0,0 +1,29 @@ +FrameExpr in vidformer::sir - Rust
vidformer::sir

Enum FrameExpr

Source
pub enum FrameExpr {
+    Source(FrameSource),
+    Filter(FilterExpr),
+}

Variants§

Implementations§

Source§

impl FrameExpr

Source

pub fn add_source_deps<'a>(&'a self, deps: &mut BTreeSet<&'a FrameSource>)

Add all referenced frame sources to a set.

+

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 u8)

🔬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..5265fd4 --- /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 u8)

🔬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..bb0f592 --- /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..d2034d0 --- /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 u8)

🔬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..4fee372 --- /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 u8)

🔬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..0a7a5d1 --- /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..dd4b126 --- /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..65ae892 --- /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..8b76d19 --- /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 u8)

🔬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..eda0f25 --- /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..8c0d321 --- /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..de85d54 --- /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..5993492 --- /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..ce6a066 --- /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..ed356ca --- /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 u8)

🔬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..795b882 --- /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..48e5d6d --- /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 u8)

🔬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..a4b2504 --- /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 u8)

🔬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..b7718d6 --- /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