├── .gitignore ├── .nowignore ├── .prettierrc ├── README.md ├── android-live-streaming ├── .gitignore ├── LICENSE ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── ic_launcher-playstore.png │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── muxlive │ │ │ ├── BroadcastActivity.java │ │ │ └── ConfigureActivity.java │ │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ └── mux.png │ │ ├── layout │ │ ├── activity_broadcast.xml │ │ └── activity_configure.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── themes.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots │ ├── animated.gif │ └── banner.png └── settings.gradle ├── astro-uploader-and-player ├── .gitignore ├── .vscode │ ├── extensions.json │ └── launch.json ├── README.md ├── astro.config.mjs ├── package-lock.json ├── package.json ├── public │ └── favicon.svg ├── src │ ├── actions │ │ └── index.ts │ ├── env.d.ts │ ├── layouts │ │ └── Layout.astro │ ├── lib │ │ └── mux.ts │ └── pages │ │ ├── index.astro │ │ ├── playback │ │ └── [playbackId].astro │ │ ├── status │ │ └── [assetId].astro │ │ └── webhook.json.ts └── tsconfig.json ├── aws-recommendation-engine ├── .gitignore ├── .npmignore ├── CODEOWNERS ├── README.md ├── bin │ └── mux-example-aws-recommendations.ts ├── cdk.json ├── jest.config.js ├── lib │ ├── kinesis-handler-lambda │ │ ├── VideoView.ts │ │ ├── event.json │ │ ├── index.ts │ │ ├── package.json │ │ ├── video_view.proto │ │ └── yarn.lock │ ├── mux-example-aws-recommendations-stack.ts │ └── recommend-lambda │ │ ├── event.json │ │ ├── index.ts │ │ ├── package.json │ │ └── yarn.lock ├── package-lock.json ├── package.json ├── test │ └── mux-example-aws-recommendations.test.ts └── tsconfig.json ├── contentful-uploader ├── .babelrc ├── .env.example ├── .gitignore ├── README.md ├── extension.json ├── now.json ├── package-lock.json ├── package.json ├── screenshots │ ├── contentful-appearance.png │ └── contentful-install-from-github.png ├── src │ ├── index.css │ ├── index.html │ ├── index.tsx │ ├── player.css │ └── preview.tsx └── tsconfig.json ├── gatsby-example-graphql ├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── env.example ├── gatsby-browser.js ├── gatsby-config.js ├── gatsby-node.js ├── package.json ├── src │ ├── components │ │ ├── video-player.js │ │ └── video-player.module.css │ ├── styles │ │ └── global.css │ └── templates │ │ └── index.js ├── static │ └── favicon.ico └── yarn.lock ├── ios-live-streaming ├── .gitignore ├── LICENSE ├── MuxLive.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── MuxLive.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── MuxLive │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-20x20@2x-1.png │ │ │ ├── Icon-App-20x20@2x-2.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-iTunes.png │ │ │ ├── icon-152.png │ │ │ ├── icon-167.png │ │ │ ├── icon-20.png │ │ │ ├── icon-29.png │ │ │ ├── icon-58.png │ │ │ ├── icon-76.png │ │ │ └── icon-80.png │ │ ├── Contents.json │ │ ├── mux-logo.imageset │ │ │ ├── Contents.json │ │ │ └── mux-logo.png │ │ └── small-mux-logo.imageset │ │ │ ├── Contents.json │ │ │ └── small-mux-logo.png │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── BroadcastViewController.swift │ ├── ConnectViewController.swift │ ├── Info.plist │ ├── MuxButton.swift │ ├── MuxTextField.swift │ └── SceneDelegate.swift ├── Podfile ├── Podfile.lock ├── README.md └── screenshots │ ├── animated.gif │ └── banner.png ├── mediarecorder-streaming-uploads ├── README.md ├── app.js └── index.html ├── nextjs-mdx-player ├── .eslintrc.json ├── .gitignore ├── README.md ├── blog │ └── awesome-blog-post.mdx ├── next.config.js ├── package-lock.json ├── package.json ├── pages │ ├── _app.js │ ├── index.js │ └── posts │ │ └── [slug].js ├── public │ ├── favicon.ico │ └── vercel.svg ├── styles │ ├── Home.module.css │ └── globals.css └── utils │ └── blogPosts.js ├── nextjs-uploader-and-player └── README.md ├── now-airtable ├── .env.example ├── README.md ├── api │ ├── add-video.js │ ├── get-video.js │ ├── list-videos.js │ └── mux-callback.js ├── components │ ├── layout.js │ ├── player.js │ └── thumbnail.js ├── next.config.js ├── now.json ├── package.json ├── pages │ ├── index.js │ ├── show.js │ └── upload.js ├── utils │ ├── airtable.js │ ├── config.js │ ├── decorate.js │ └── theme.js └── yarn.lock ├── remixjs-uploader-and-player └── README.md ├── signed-playback-lambda ├── .gitignore ├── README.md ├── lambda.js ├── package.json ├── webpack.config.js └── yarn.lock ├── signed-playback-netlify ├── .gitignore ├── README.md ├── functions │ └── sign_playback_id.js ├── netlify.toml ├── package.json ├── src │ └── mux_signatures.js └── yarn.lock ├── sveltekit-uploader-and-player ├── .env.example ├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── README.md ├── package-lock.json ├── package.json ├── postcss.config.cjs ├── src │ ├── app.d.ts │ ├── app.html │ ├── app.pcss │ ├── lib │ │ └── mux.ts │ └── routes │ │ ├── +layout.svelte │ │ ├── +page.server.ts │ │ ├── +page.svelte │ │ ├── api │ │ └── mux │ │ │ └── webhook │ │ │ └── +server.ts │ │ ├── playback │ │ └── [playbackId] │ │ │ └── +page.svelte │ │ └── status │ │ └── [assetId] │ │ ├── +page.server.ts │ │ └── +page.svelte ├── static │ └── favicon.png ├── svelte.config.js ├── tailwind.config.cjs ├── tsconfig.json └── vite.config.ts ├── swift-data-library-installation ├── MuxDataContainer │ ├── .swiftpm │ │ └── xcode │ │ │ └── package.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Package.swift │ ├── Sources │ │ └── MuxDataContainer │ │ │ ├── MonitoringContainer.swift │ │ │ └── ProcessInfo+Mux.swift │ └── Tests │ │ └── MuxDataContainerTests │ │ └── MuxDataContainerTests.swift ├── README.md └── SwiftDataLibraryInstallation │ ├── SwiftDataLibraryInstallation.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── SwiftDataLibraryInstallation.xcscheme │ ├── SwiftDataLibraryInstallation │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── BasicPlaybackExampleViewController.swift │ ├── Info.plist │ ├── PlayerLayerExampleViewController.swift │ └── SceneDelegate.swift │ ├── SwiftDataLibraryInstallationTests │ └── SwiftDataLibraryInstallationTests.swift │ └── SwiftDataLibraryInstallationUITests │ ├── SwiftDataLibraryInstallationUITests.swift │ └── SwiftDataLibraryInstallationUITestsLaunchTests.swift ├── swift-video-app ├── MuxExampleVideoApp │ ├── MuxExampleVideoApp.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ ├── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── swiftpm │ │ │ │ │ └── Package.resolved │ │ │ └── xcuserdata │ │ │ │ └── dylanjhaveri.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── MuxExampleVideoApp.xcscheme │ │ └── xcuserdata │ │ │ └── dylanjhaveri.xcuserdatad │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ ├── MuxExampleVideoApp │ │ ├── .gitignore │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AccentColor.colorset │ │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── BasicPlaybackExampleViewController.swift │ │ ├── Info.plist │ │ ├── PlayerLayerExampleViewController.swift │ │ └── SceneDelegate.swift │ ├── MuxExampleVideoAppTests │ │ ├── Info.plist │ │ └── MuxExampleVideoAppTests.swift │ └── MuxExampleVideoAppUITests │ │ ├── Info.plist │ │ └── MuxExampleVideoAppUITests.swift └── README.md └── webhook-notifications-knock ├── .env.example ├── .eslintrc.json ├── .gitignore ├── README.md ├── app ├── api │ ├── knock │ │ ├── channels │ │ │ └── route.ts │ │ ├── on-play │ │ │ └── route.ts │ │ └── subscriptions │ │ │ └── route.ts │ └── webhooks │ │ └── mux │ │ ├── route.ts │ │ ├── video.asset.ready.json │ │ └── video.live_stream.active.json ├── components │ ├── ApiTriggers.tsx │ ├── FeedContainer.tsx │ ├── FeedToasts.tsx │ ├── SubscribeButton.tsx │ ├── SubscriberCount.tsx │ └── player.tsx ├── favicon.ico ├── globals.css ├── layout.tsx ├── lib │ └── knock.ts ├── page.tsx ├── trigger-apis │ └── page.tsx └── users │ └── [userId] │ └── page.tsx ├── next.config.mjs ├── package-lock.json ├── package.json ├── postcss.config.js ├── public ├── next.svg ├── placeholder-user.jpg ├── placeholder.svg └── vercel.svg ├── tailwind.config.ts └── tsconfig.json /.nowignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .cache 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "singleQuote": true 5 | } 6 | -------------------------------------------------------------------------------- /android-live-streaming/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Built application files 3 | *.apk 4 | *.aar 5 | *.ap_ 6 | *.aab 7 | 8 | # Files for the ART/Dalvik VM 9 | *.dex 10 | 11 | # Java class files 12 | *.class 13 | 14 | # Generated files 15 | bin/ 16 | gen/ 17 | out/ 18 | # Uncomment the following line in case you need and you don't have the release build type files in your app 19 | # release/ 20 | 21 | # Gradle files 22 | .gradle/ 23 | build/ 24 | 25 | # Local configuration file (sdk path, etc) 26 | local.properties 27 | 28 | # Proguard folder generated by Eclipse 29 | proguard/ 30 | 31 | # Log Files 32 | *.log 33 | 34 | # Android Studio Navigation editor temp files 35 | .navigation/ 36 | 37 | # Android Studio captures folder 38 | captures/ 39 | 40 | # IntelliJ 41 | .idea/ 42 | *.iml 43 | .idea/workspace.xml 44 | .idea/tasks.xml 45 | .idea/gradle.xml 46 | .idea/assetWizardSettings.xml 47 | .idea/dictionaries 48 | .idea/libraries 49 | # Android Studio 3 in .gitignore file. 50 | .idea/caches 51 | .idea/modules.xml 52 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 53 | .idea/navEditor.xml 54 | 55 | # Keystore files 56 | # Uncomment the following lines if you do not want to check your keystore files in. 57 | #*.jks 58 | #*.keystore 59 | 60 | # External native build folder generated in Android Studio 2.2 and later 61 | .externalNativeBuild 62 | .cxx/ 63 | 64 | # Google Services (e.g. APIs or Firebase) 65 | # google-services.json 66 | 67 | # Freeline 68 | freeline.py 69 | freeline/ 70 | freeline_project_description.json 71 | 72 | # fastlane 73 | fastlane/report.xml 74 | fastlane/Preview.html 75 | fastlane/screenshots 76 | fastlane/test_output 77 | fastlane/readme.md 78 | 79 | # Version control 80 | vcs.xml 81 | 82 | # lint 83 | lint/intermediates/ 84 | lint/generated/ 85 | lint/outputs/ 86 | lint/tmp/ 87 | # lint/reports/ 88 | 89 | # Android Profiling 90 | *.hprof 91 | 92 | 93 | **/.idea/workspace.xml 94 | **/.idea/tasks.xml 95 | 96 | .DS_Store 97 | *~ 98 | -------------------------------------------------------------------------------- /android-live-streaming/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Mux, Inc. 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. -------------------------------------------------------------------------------- /android-live-streaming/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android-live-streaming/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | 5 | android { 6 | compileSdkVersion 30 7 | buildToolsVersion "29.0.3" 8 | 9 | defaultConfig { 10 | applicationId "com.example.muxlive" 11 | minSdkVersion 21 12 | targetSdkVersion 30 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | compileOptions { 26 | sourceCompatibility JavaVersion.VERSION_1_8 27 | targetCompatibility JavaVersion.VERSION_1_8 28 | } 29 | } 30 | 31 | dependencies { 32 | 33 | implementation 'androidx.appcompat:appcompat:1.1.0' 34 | implementation 'com.google.android.material:material:1.1.0' 35 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 36 | implementation 'com.github.pedroSG94.rtmp-rtsp-stream-client-java:rtplibrary:1.9.5' 37 | testImplementation 'junit:junit:4.+' 38 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 39 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 40 | } 41 | -------------------------------------------------------------------------------- /android-live-streaming/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 19 | 20 | 27 | 30 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | 31 | -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/drawable/mux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/drawable/mux.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | #FB2490 11 | #AB1B64 12 | 13 | -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #211F1F 4 | 5 | -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Mux Live 3 | 4 | -------------------------------------------------------------------------------- /android-live-streaming/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | -------------------------------------------------------------------------------- /android-live-streaming/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath "com.android.tools.build:gradle:4.1.1" 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | maven { url 'https://jitpack.io' } 20 | } 21 | } 22 | 23 | task clean(type: Delete) { 24 | delete rootProject.buildDir 25 | } 26 | -------------------------------------------------------------------------------- /android-live-streaming/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | -------------------------------------------------------------------------------- /android-live-streaming/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android-live-streaming/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Dec 03 11:36:30 GMT 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip 7 | -------------------------------------------------------------------------------- /android-live-streaming/screenshots/animated.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/screenshots/animated.gif -------------------------------------------------------------------------------- /android-live-streaming/screenshots/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/android-live-streaming/screenshots/banner.png -------------------------------------------------------------------------------- /android-live-streaming/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name = "MuxLive" 3 | -------------------------------------------------------------------------------- /astro-uploader-and-player/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | 4 | # generated types 5 | .astro/ 6 | 7 | # dependencies 8 | node_modules/ 9 | 10 | # logs 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | 23 | # jetbrains setting folder 24 | .idea/ 25 | -------------------------------------------------------------------------------- /astro-uploader-and-player/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /astro-uploader-and-player/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /astro-uploader-and-player/astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | 3 | // https://astro.build/config 4 | export default defineConfig({ 5 | output: 'server', 6 | experimental: { 7 | actions: true, 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /astro-uploader-and-player/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "astro-uploader-and-player", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro check && astro build", 9 | "preview": "astro preview", 10 | "astro": "astro" 11 | }, 12 | "dependencies": { 13 | "@astrojs/check": "^0.7.0", 14 | "@mux/mux-node": "^8.7.1", 15 | "@mux/mux-player": "^2.7.0", 16 | "@mux/mux-uploader": "^1.0.0-beta.18", 17 | "astro": "^4.10.0", 18 | "typescript": "^5.4.5" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /astro-uploader-and-player/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /astro-uploader-and-player/src/actions/index.ts: -------------------------------------------------------------------------------- 1 | import { defineAction, z } from 'astro:actions'; 2 | import mux from '../lib/mux'; 3 | 4 | export const server = { 5 | getAssetForUpload: defineAction({ 6 | accept: 'form', 7 | input: z.object({ 8 | uploadId: z.string(), 9 | }), 10 | handler: async ({ uploadId }) => { 11 | // when the upload is complete, 12 | // the upload will have an assetId associated with it 13 | // we'll use that assetId to view the video status 14 | const upload = await mux.video.uploads.retrieve(uploadId); 15 | console.log({ uploadId, upload }); 16 | if (upload.asset_id) { 17 | return { assetId: upload.asset_id }; 18 | } 19 | 20 | // while onSuccess is a strong indicator that Mux has received the file 21 | // and created the asset, this isn't a guarantee. 22 | // In production, you might write an api route 23 | // to listen for the`video.upload.asset_created` webhook 24 | // https://docs.mux.com/guides/listen-for-webhooks 25 | // However, to keep things simple here, 26 | // we'll just ask the user to push the button again. 27 | // This should rarely happen. 28 | return { message: 'Upload has no asset yet. Try again.' }; 29 | }, 30 | }), 31 | }; 32 | -------------------------------------------------------------------------------- /astro-uploader-and-player/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /astro-uploader-and-player/src/layouts/Layout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | interface Props { 3 | title: string; 4 | } 5 | 6 | const { title } = Astro.props; 7 | --- 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {title} 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /astro-uploader-and-player/src/lib/mux.ts: -------------------------------------------------------------------------------- 1 | import Mux from '@mux/mux-node'; 2 | 3 | const mux = new Mux({ 4 | tokenId: import.meta.env.MUX_TOKEN_ID, 5 | tokenSecret: import.meta.env.MUX_TOKEN_SECRET, 6 | }); 7 | 8 | export default mux; 9 | -------------------------------------------------------------------------------- /astro-uploader-and-player/src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '../layouts/Layout.astro'; 3 | import mux from '../lib/mux'; 4 | 5 | const upload = await mux.video.uploads.create({ 6 | new_asset_settings: { 7 | playback_policy: ['public'], 8 | encoding_tier: 'baseline', 9 | }, 10 | cors_origin: '*', 11 | }); 12 | --- 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 |
21 | 50 |
51 | -------------------------------------------------------------------------------- /astro-uploader-and-player/src/pages/playback/[playbackId].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '../../layouts/Layout.astro'; 3 | 4 | const { playbackId } = Astro.params; 5 | 6 | const title = 'View this video created with Mux + Astro'; 7 | const description = 8 | 'This video was uploaded and processed by Mux in an example Remix application.'; 9 | --- 10 | 11 | 12 | 13 | 14 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 39 | 40 | 41 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /astro-uploader-and-player/src/pages/status/[assetId].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '../../layouts/Layout.astro'; 3 | import mux from '../../lib/mux'; 4 | 5 | const { assetId } = Astro.params; 6 | 7 | // now that we have an assetId, we can see how the video is doing. 8 | // in production, you might have some setup where a Mux webhook 9 | // tells your server the status of your asset. 10 | // https://docs.mux.com/guides/listen-for-webhooks 11 | // for this example, however, we'll just ask the Mux API ourselves 12 | if (typeof assetId !== 'string') { 13 | return new Response(null, { 14 | status: 404, 15 | statusText: 'Not found', 16 | }); 17 | } 18 | const asset = await mux.video.assets.retrieve(assetId); 19 | 20 | // if the asset is ready and it has a public playback ID, 21 | // (which it should, considering the upload settings we used) 22 | // redirect to its playback page 23 | if (asset.status === 'ready') { 24 | const playbackIds = asset.playback_ids; 25 | if (Array.isArray(playbackIds)) { 26 | const playbackId = playbackIds.find((id) => id.policy === 'public'); 27 | if (playbackId) { 28 | return Astro.redirect(`/playback/${playbackId.id}`); 29 | } 30 | } 31 | } 32 | --- 33 | 34 | 35 | { 36 | // in most cases, the asset is just preparing. 37 | // Let's say something to that effect. 38 | asset.status === 'preparing' ? ( 39 |

Asset is preparing...

40 | ) : ( 41 | // if not "preparing", then "errored" or "ready" 42 | // if "errored", we'll show the errors 43 | // we don't expect to see "ready" because "ready" should redirect in the loader 44 | 45 |

46 | Asset is in an unexpected state: {status}. 47 |

48 | {Array.isArray(asset.errors) ? ( 49 |
    50 | {asset.errors.map((error, key) => ( 51 |
  • {JSON.stringify(error)}
  • 52 | ))} 53 |
54 | ) : null} 55 |

56 | This is awkward. Let's refresh and try again. 57 |

58 |
59 | ) 60 | } 61 | 62 | 63 | 68 |
69 | -------------------------------------------------------------------------------- /astro-uploader-and-player/src/pages/webhook.json.ts: -------------------------------------------------------------------------------- 1 | import type { APIRoute } from 'astro'; 2 | import mux from '../lib/mux'; 3 | 4 | // while this isn't called anywhere in this example, 5 | // I thought it might be helpful to see what a mux webhook handler looks like. 6 | 7 | export const POST: APIRoute = async ({ request }) => { 8 | const body = await request.text(); 9 | // mux.webhooks.unwrap will validate that the given payload was sent by Mux and parse the payload. 10 | // It will also provide type-safe access to the payload. 11 | // Generate MUX_WEBHOOK_SIGNING_SECRET in the Mux dashboard 12 | // https://dashboard.mux.com/settings/webhooks 13 | const event = mux.webhooks.unwrap( 14 | body, 15 | request.headers, 16 | process.env.MUX_WEBHOOK_SIGNING_SECRET 17 | ); 18 | 19 | // you can also unwrap the payload yourself: 20 | // const event = await request.json(); 21 | switch (event.type) { 22 | case 'video.upload.asset_created': 23 | // we might use this to know that an upload has been completed 24 | // and we can save its assetId to our database 25 | break; 26 | case 'video.asset.ready': 27 | // we might use this to know that a video has been encoded 28 | // and we can save its playbackId to our database 29 | break; 30 | // there are many more Mux webhook events 31 | // check them out at https://docs.mux.com/webhook-reference 32 | default: 33 | break; 34 | } 35 | 36 | return new Response(JSON.stringify({ message: 'ok' }), { 37 | headers: { 38 | 'Content-Type': 'application/json', 39 | }, 40 | }); 41 | }; 42 | -------------------------------------------------------------------------------- /astro-uploader-and-player/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict" 3 | } -------------------------------------------------------------------------------- /aws-recommendation-engine/.gitignore: -------------------------------------------------------------------------------- 1 | *.js 2 | !jest.config.js 3 | *.d.ts 4 | node_modules 5 | 6 | # CDK asset staging directory 7 | .cdk.staging 8 | cdk.out 9 | -------------------------------------------------------------------------------- /aws-recommendation-engine/.npmignore: -------------------------------------------------------------------------------- 1 | *.ts 2 | !*.d.ts 3 | 4 | # CDK asset staging directory 5 | .cdk.staging 6 | cdk.out 7 | -------------------------------------------------------------------------------- /aws-recommendation-engine/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @muxinc/community-engineering 2 | /CODEOWNERS @muxinc/platform-engineering 3 | -------------------------------------------------------------------------------- /aws-recommendation-engine/README.md: -------------------------------------------------------------------------------- 1 | # Mux AWS recommendation engine example 2 | 3 | This repository contains an example implementation of how you can set up Mux streaming exports and Amazon Personalize to build your own content recommendation engine. 4 | 5 | For a detailed walkthrough on how you can use this repository, check out the [corollary blog post](https://mux.com/blog/amazon-personalize-video-recommendation-engine) over on the Mux blog. 6 | ## Useful commands 7 | 8 | * `npm run build` compile typescript to js 9 | * `npm run watch` watch for changes and compile 10 | * `npm run test` perform the jest unit tests 11 | * `cdk deploy` deploy this stack to your default AWS account/region 12 | * `cdk diff` compare deployed stack with current state 13 | * `cdk synth` emits the synthesized CloudFormation template 14 | ## References and resources 15 | * https://docs.aws.amazon.com/general/latest/gr/personalize.html 16 | * https://github.com/aws-samples/amazon-personalize-ingestion-pipeline 17 | * https://github.com/CloudedThings/100-Days-in-Cloud/blob/main/Labs/80-Amazon-Rekognition-CDK-deployed/index.py 18 | * https://github.com/aws-samples/amazon-rekognition-large-scale-processing 19 | * https://docs.aws.amazon.com/personalize/latest/dg/recording-events.html#event-record-api 20 | * https://docs.aws.amazon.com/personalize/latest/dg/API_UBS_PutItems.html 21 | * https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-personalize-events/classes/putitemscommand.html 22 | -------------------------------------------------------------------------------- /aws-recommendation-engine/bin/mux-example-aws-recommendations.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import 'source-map-support/register'; 3 | import * as cdk from 'aws-cdk-lib'; 4 | import { MuxExampleAwsRecommendationsStack } from '../lib/mux-example-aws-recommendations-stack'; 5 | 6 | const app = new cdk.App(); 7 | new MuxExampleAwsRecommendationsStack(app, 'MuxExampleAwsRecommendationsStack', { 8 | /* If you don't specify 'env', this stack will be environment-agnostic. 9 | * Account/Region-dependent features and context lookups will not work, 10 | * but a single synthesized template can be deployed anywhere. */ 11 | 12 | /* Uncomment the next line to specialize this stack for the AWS Account 13 | * and Region that are implied by the current CLI configuration. */ 14 | // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION }, 15 | 16 | /* Uncomment the next line if you know exactly what Account and Region you 17 | * want to deploy the stack to. */ 18 | // env: { account: '123456789012', region: 'us-east-1' }, 19 | 20 | /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */ 21 | }); -------------------------------------------------------------------------------- /aws-recommendation-engine/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node --prefer-ts-exts bin/mux-example-aws-recommendations.ts", 3 | "watch": { 4 | "include": [ 5 | "**" 6 | ], 7 | "exclude": [ 8 | "README.md", 9 | "cdk*.json", 10 | "**/*.d.ts", 11 | "**/*.js", 12 | "tsconfig.json", 13 | "package*.json", 14 | "yarn.lock", 15 | "node_modules", 16 | "test" 17 | ] 18 | }, 19 | "context": { 20 | "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, 21 | "@aws-cdk/core:stackRelativeExports": true, 22 | "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, 23 | "@aws-cdk/aws-lambda:recognizeVersionProps": true, 24 | "@aws-cdk/aws-lambda:recognizeLayerVersion": true, 25 | "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true, 26 | "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, 27 | "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, 28 | "@aws-cdk/core:checkSecretUsage": true, 29 | "@aws-cdk/aws-iam:minimizePolicies": true, 30 | "@aws-cdk/core:validateSnapshotRemovalPolicy": true, 31 | "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, 32 | "@aws-cdk/core:target-partitions": [ 33 | "aws", 34 | "aws-cn" 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /aws-recommendation-engine/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | roots: ['/test'], 4 | testMatch: ['**/*.test.ts'], 5 | transform: { 6 | '^.+\\.tsx?$': 'ts-jest' 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /aws-recommendation-engine/lib/kinesis-handler-lambda/event.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [{ 3 | "Sns": { 4 | "Type": "Notification", 5 | MessageId: '88daf6f7-3f55-5fda-85dc-adc9596a88ba', 6 | TopicArn: 'arn:aws:sns:us-east-1:618963333842:AmazonRekognitionMuxVideo', 7 | Subject: null, 8 | Message: '{"JobId":"9864ee6a6d33bc4c3a195ab868720ea532567617e5049631d16e93478411da61","Status":"SUCCEEDED","API":"StartLabelDetection","JobTag":"string","Timestamp":1657037823845,"Video":{"S3ObjectName":"hackweek-mux-video-ad-final.mp4","S3Bucket":"dk-videos-bucket"}}', 9 | Timestamp: '2022-07-05T16:17:03.978Z', 10 | SignatureVersion: '1', 11 | Signature: 'LXrafz0da/y67FFTR323zUDxWSKtut9evVgolpI1KhtyG8nsWxlMEcaCACDve//0Ar9SDMcTnSdUt8RckwheYjdEIJpUb9SsmEWqlkU77qN5vDBk5rP/Bf92cBxiranSZLx9Y3cZjQAvSSUvbVz0VWJRn8U6TXd9yE0CsQQG+Qm6hJQNpVm740o2XxG6oIynd+JWBdS342/vmsQypnFy0uI3UD4lOknqKKF8TgzQN9xNLM/IOdln+oHBx3XWESCLJI1PLHcuG3CV1xKGq1+UaGIIHJa+JpnhBHtJNwxGKR8CBvYeogbhZVBbAYXrSXWUUbp9RNT6kT/HDbhAhOL1lw==', 12 | SigningCertUrl: 'https://sns.us-east-1.amazonaws.com/SimpleNotificationService-7ff5318490ec183fbaddaa2a969abfda.pem', 13 | UnsubscribeUrl: 'https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:618963333842:AmazonRekognitionMuxVideo:ff670b88-c438-4ecb-a3ad-543dd6fd4979', 14 | MessageAttributes: {} 15 | } 16 | }] 17 | } -------------------------------------------------------------------------------- /aws-recommendation-engine/lib/kinesis-handler-lambda/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lambda", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@aws-sdk/client-personalize-events": "^3.121.0", 8 | "@aws-sdk/client-rekognition": "^3.118.1", 9 | "@mux/mux-node": "^5.1.0", 10 | "protobufjs": "^7.0.0", 11 | "typescript": "^4.7.4" 12 | }, 13 | "devDependencies": { 14 | "@types/aws-lambda": "^8.10.101" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /aws-recommendation-engine/lib/recommend-lambda/event.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /aws-recommendation-engine/lib/recommend-lambda/index.ts: -------------------------------------------------------------------------------- 1 | import { PersonalizeRuntimeClient, GetRecommendationsCommand, PredictedItem } from "@aws-sdk/client-personalize-runtime"; 2 | 3 | import { APIGatewayEvent, Context } from "aws-lambda"; 4 | const personalizeClient = new PersonalizeRuntimeClient({ region: process.env.AWS_REGION }); 5 | 6 | const MOST_POPULAR_RECOMMENDER = "arn:aws:personalize:::recipe/aws-vod-most-popular"; 7 | const BECAUSE_YOU_WATCHED_X_RECOMMENDER = "arn:aws:personalize:::recipe/aws-vod-because-you-watched-x"; 8 | const TOP_PICKS_FOR_YOU_RECOMMENDER = "arn:aws:personalize:::recipe/aws-vod-top-picks"; 9 | 10 | exports.handler = async function (event: APIGatewayEvent, context: Context): Promise { 11 | try { 12 | 13 | const userId = event.queryStringParameters?.viewerUserId || "anonymous" 14 | const assetId = event.queryStringParameters?.assetId || "anonymous" 15 | 16 | const response = await personalizeClient.send( 17 | new GetRecommendationsCommand({ 18 | userId, 19 | itemId: assetId, 20 | recommenderArn: MOST_POPULAR_RECOMMENDER, // change this out with the ARN representing your desired recommendation strategy 21 | context: {} 22 | }) 23 | ); 24 | 25 | return response.itemList || []; 26 | 27 | // process data. 28 | } catch (error) { 29 | console.log(JSON.stringify(error, null, 2)); 30 | // error handling. 31 | } 32 | 33 | return []; 34 | } 35 | -------------------------------------------------------------------------------- /aws-recommendation-engine/lib/recommend-lambda/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lambda", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@aws-sdk/client-personalize-events": "^3.121.0", 8 | "@aws-sdk/client-personalize-runtime": "^3.145.0", 9 | "@aws-sdk/client-rekognition": "^3.118.1", 10 | "@mux/mux-node": "^5.1.0", 11 | "protobufjs": "^7.0.0", 12 | "typescript": "^4.7.4" 13 | }, 14 | "devDependencies": { 15 | "@types/aws-lambda": "^8.10.101" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /aws-recommendation-engine/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mux-example-aws-recommendations", 3 | "version": "0.1.0", 4 | "bin": { 5 | "mux-example-aws-recommendations": "bin/mux-example-aws-recommendations.js" 6 | }, 7 | "scripts": { 8 | "build": "tsc", 9 | "watch": "tsc -w", 10 | "test": "jest", 11 | "cdk": "cdk" 12 | }, 13 | "devDependencies": { 14 | "@types/jest": "^27.5.2", 15 | "@types/node": "^10.17.27", 16 | "@types/prettier": "2.6.0", 17 | "aws-cdk": "2.29.1", 18 | "esbuild": "^0.14.48", 19 | "jest": "^27.5.1", 20 | "ts-jest": "^27.1.4", 21 | "ts-node": "^10.8.1", 22 | "typescript": "~3.9.7" 23 | }, 24 | "dependencies": { 25 | "aws-cdk-lib": "2.29.1", 26 | "constructs": "^10.0.0", 27 | "source-map-support": "^0.5.21" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /aws-recommendation-engine/test/mux-example-aws-recommendations.test.ts: -------------------------------------------------------------------------------- 1 | // import * as cdk from 'aws-cdk-lib'; 2 | // import { Template } from 'aws-cdk-lib/assertions'; 3 | // import * as MuxExampleAwsRecommendations from '../lib/mux-example-aws-recommendations-stack'; 4 | 5 | // example test. To run these tests, uncomment this file along with the 6 | // example resource in lib/mux-example-aws-recommendations-stack.ts 7 | test('SQS Queue Created', () => { 8 | // const app = new cdk.App(); 9 | // // WHEN 10 | // const stack = new MuxExampleAwsRecommendations.MuxExampleAwsRecommendationsStack(app, 'MyTestStack'); 11 | // // THEN 12 | // const template = Template.fromStack(stack); 13 | 14 | // template.hasResourceProperties('AWS::SQS::Queue', { 15 | // VisibilityTimeout: 300 16 | // }); 17 | }); 18 | -------------------------------------------------------------------------------- /aws-recommendation-engine/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "commonjs", 5 | "lib": [ 6 | "es2018" 7 | ], 8 | "declaration": true, 9 | "strict": true, 10 | "noImplicitAny": true, 11 | "strictNullChecks": true, 12 | "noImplicitThis": true, 13 | "alwaysStrict": true, 14 | "noUnusedLocals": false, 15 | "noUnusedParameters": false, 16 | "noImplicitReturns": true, 17 | "noFallthroughCasesInSwitch": false, 18 | "inlineSourceMap": true, 19 | "inlineSources": true, 20 | "experimentalDecorators": true, 21 | "strictPropertyInitialization": false, 22 | "typeRoots": [ 23 | "./node_modules/@types" 24 | ] 25 | }, 26 | "exclude": [ 27 | "node_modules", 28 | "cdk.out" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /contentful-uploader/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "useBuiltIns": false, 7 | "modules": false 8 | } 9 | ], 10 | [ 11 | "@babel/preset-react", 12 | { 13 | "useBuiltIns": true 14 | } 15 | ] 16 | ], 17 | "plugins": [ 18 | [ 19 | "@babel/plugin-proposal-class-properties", 20 | { 21 | "loose": true 22 | } 23 | ], 24 | [ 25 | "@babel/plugin-transform-runtime", 26 | { 27 | "corejs": false, 28 | "helpers": false, 29 | "regenerator": true 30 | } 31 | ] 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /contentful-uploader/.env.example: -------------------------------------------------------------------------------- 1 | MUX_TOKEN_ID=your-access-token-id 2 | MUX_TOKEN_SECRET=your-access-token-secret 3 | -------------------------------------------------------------------------------- /contentful-uploader/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # dotenv environment variables file 9 | .env 10 | .contentfulrc.json 11 | 12 | # Parcel-bundler cache 13 | .cache 14 | 15 | # Dependency directories 16 | node_modules/ 17 | 18 | # Build 19 | build/ 20 | -------------------------------------------------------------------------------- /contentful-uploader/extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "mux-contentful-uploader", 3 | "name": "Mux Contentful Uploader", 4 | "src": "https://contentful.mux.dev/extension", 5 | "fieldTypes": ["Object"], 6 | "parameters": { 7 | "installation": [ 8 | { 9 | "id": "muxAccessTokenId", 10 | "name": "Mux Access Token ID", 11 | "description": "You can create access tokens here: https://dashboard.mux.com/settings/access-tokens", 12 | "type": "Symbol", 13 | "required": true 14 | }, 15 | { 16 | "id": "muxAccessTokenSecret", 17 | "name": "Mux Access Token Secret", 18 | "description": "You can create access tokens here: https://dashboard.mux.com/settings/access-tokens", 19 | "type": "Symbol", 20 | "required": true 21 | } 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contentful-uploader/now.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "alias": "contentful.mux.dev", 4 | "builds": [ 5 | { 6 | "src": "screenshots/*.png", 7 | "use": "@now/static" 8 | }, 9 | { 10 | "src": "*.md", 11 | "use": "@now/md", 12 | "config": { 13 | "title": "Contentful Mux Video Plugin", 14 | "language": "en", 15 | "meta": [ 16 | { 17 | "name": "description", 18 | "content": "Add beautiful video streaming to your Contentful dashboard! Mux Video extension that's installed in minutes" 19 | } 20 | ], 21 | "css": ["https://static.mux.com/css/mux-markdown.css"] 22 | } 23 | }, 24 | { 25 | "src": "package.json", 26 | "use": "@now/static-build", 27 | "config": { "distDir": "build" } 28 | } 29 | ], 30 | "routes": [ 31 | { "src": "/", "dest": "/README.html" }, 32 | { "src": "/extension", "dest": "index.html" } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /contentful-uploader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mux-contentful-uploader", 3 | "version": "0.1.0", 4 | "private": true, 5 | "devDependencies": { 6 | "@babel/core": "7.3.4", 7 | "@babel/plugin-proposal-class-properties": "7.3.4", 8 | "@babel/plugin-transform-runtime": "7.3.4", 9 | "@babel/preset-env": "7.3.4", 10 | "@babel/preset-react": "7.0.0", 11 | "@contentful/contentful-extension-scripts": "0.7.1", 12 | "@types/react": "^16.8.8", 13 | "@types/react-dom": "^16.8.3", 14 | "@types/webpack-env": "1.13.9", 15 | "contentful-cli": "0.26.1", 16 | "cssnano": "4.1.10", 17 | "typescript": "3.3.4000" 18 | }, 19 | "dependencies": { 20 | "@contentful/forma-36-fcss": "^0.0.16", 21 | "@contentful/forma-36-react-components": "^2.10.3", 22 | "@contentful/forma-36-tokens": "^0.2.3", 23 | "@mux/upchunk": "^1.0.6", 24 | "@types/hls.js": "^0.12.3", 25 | "contentful-ui-extensions-sdk": "3.7.2", 26 | "hls.js": "^0.12.4", 27 | "prop-types": "^15.7.2", 28 | "react": "^16.8.5", 29 | "react-dom": "^16.8.5" 30 | }, 31 | "scripts": { 32 | "prestart": "contentful extension update --src http://localhost:1234 --force", 33 | "start": "contentful-extension-scripts start", 34 | "build": "contentful-extension-scripts build", 35 | "deploy": "npm run build && now", 36 | "configure": "contentful space use && contentful space environment use", 37 | "login": "contentful login", 38 | "logout": "contentful logout", 39 | "help": "contentful-extension-scripts help", 40 | "now-build": "npm run build", 41 | "install-extension": "eval `cat .env` && contentful extension create --installation-parameters '{\"muxAccessTokenId\": \"'$MUX_TOKEN_ID'\", \"muxAccessTokenSecret\": \"'$MUX_TOKEN_SECRET'\"}'" 42 | }, 43 | "browserslist": [ 44 | "last 5 Chrome version", 45 | "> 1%", 46 | "not ie <= 11" 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /contentful-uploader/screenshots/contentful-appearance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/contentful-uploader/screenshots/contentful-appearance.png -------------------------------------------------------------------------------- /contentful-uploader/screenshots/contentful-install-from-github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muxinc/examples/b4ec828052003854aa6b3037f59bb655440b1f11/contentful-uploader/screenshots/contentful-install-from-github.png -------------------------------------------------------------------------------- /contentful-uploader/src/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body, 3 | div { 4 | margin: 0; 5 | padding: 0; 6 | border: 0; 7 | font-size: 100%; 8 | font: inherit; 9 | vertical-align: baseline; 10 | } 11 | 12 | .progress { 13 | margin-bottom: 16px; 14 | height: 12px; 15 | background-image: linear-gradient(0deg, #0eb87f, #14d997); 16 | border-radius: 0.125rem; 17 | transition: width 1s ease; 18 | } 19 | 20 | .progress::after { 21 | content: ''; 22 | position: absolute; 23 | top: 0; 24 | left: 0; 25 | bottom: 0; 26 | right: 0; 27 | background-image: linear-gradient( 28 | -45deg, 29 | rgba(255, 255, 255, 0.2) 25%, 30 | transparent 25%, 31 | transparent 50%, 32 | rgba(255, 255, 255, 0.2) 50%, 33 | rgba(255, 255, 255, 0.2) 75%, 34 | transparent 75%, 35 | transparent 36 | ); 37 | z-index: 1; 38 | background-size: 50px 50px; 39 | animation: move 2s linear infinite; 40 | border-top-right-radius: 8px; 41 | border-bottom-right-radius: 8px; 42 | border-top-left-radius: 20px; 43 | border-bottom-left-radius: 20px; 44 | overflow: hidden; 45 | } 46 | -------------------------------------------------------------------------------- /contentful-uploader/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /contentful-uploader/src/player.css: -------------------------------------------------------------------------------- 1 | .player { 2 | padding: 2em; 3 | } 4 | -------------------------------------------------------------------------------- /contentful-uploader/src/preview.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Hls = require('hls.js'); 3 | import './player.css'; 4 | 5 | interface PlayerProps { 6 | playbackId: string; 7 | } 8 | 9 | class Player extends React.Component { 10 | playerRef: React.RefObject; 11 | hls: Hls; 12 | 13 | constructor(props: PlayerProps) { 14 | super(props); 15 | 16 | this.playerRef = React.createRef(); 17 | this.hls = new Hls(); 18 | } 19 | 20 | componentDidMount() { 21 | if (!this.playerRef.current) { 22 | throw Error('No reference to an existing video element found.'); 23 | } 24 | 25 | if (Hls.isSupported()) { 26 | this.hls.loadSource(this.playbackUrl()); 27 | this.hls.attachMedia(this.playerRef.current); 28 | } else if ( 29 | this.playerRef.current.canPlayType('application/vnd.apple.mpegurl') 30 | ) { 31 | this.playerRef.current.src = this.playbackUrl(); 32 | } 33 | } 34 | 35 | playbackUrl = () => `https://stream.mux.com/${this.props.playbackId}.m3u8`; 36 | posterUrl = () => 37 | `https://image.mux.com/${this.props.playbackId}/thumbnail.jpg`; 38 | 39 | render() { 40 | return ( 41 |
42 |
49 | ); 50 | } 51 | } 52 | 53 | export default Player; 54 | -------------------------------------------------------------------------------- /contentful-uploader/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "strict": true, 6 | "jsx": "react", 7 | "rootDir": "./src", 8 | "experimentalDecorators": true, 9 | "lib": ["dom", "es2015"], 10 | "resolveJsonModule": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /gatsby-example-graphql/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variable files 55 | .env* 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | 64 | # Yarn 65 | yarn-error.log 66 | .pnp/ 67 | .pnp.js 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | -------------------------------------------------------------------------------- /gatsby-example-graphql/.prettierignore: -------------------------------------------------------------------------------- 1 | .cache 2 | package.json 3 | package-lock.json 4 | public 5 | -------------------------------------------------------------------------------- /gatsby-example-graphql/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "semi": false 4 | } 5 | -------------------------------------------------------------------------------- /gatsby-example-graphql/LICENSE: -------------------------------------------------------------------------------- 1 | The BSD Zero Clause License (0BSD) 2 | 3 | Copyright (c) 2020 Gatsby Inc. 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 | PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /gatsby-example-graphql/README.md: -------------------------------------------------------------------------------- 1 | # Gatsby + Mux (GraphQL example) 2 | 3 | This is an example Gatsby site that uses [Mux](https://mux.com/) and Mux's GraphQL API powered by [OneGraph](https://www.onegraph.com/) 4 | 5 | ## Usage 6 | 7 | This project was generated with `gatsby new` based on the [hello world example](https://github.com/gatsbyjs/gatsby-starter-hello-world). 8 | 9 | To use this example you will need a free [OneGraph](https://www.onegraph.com) App and a free [Mux](https://mux.com/) account. 10 | 11 | 1. Copy `env.example` to `.env.development`. Add your Mux keys and onegraph APP ID 12 | 1. `yarn dev` will start the gatsby server 13 | 1. This app has a single index page with a list of your Mux assets 14 | -------------------------------------------------------------------------------- /gatsby-example-graphql/env.example: -------------------------------------------------------------------------------- 1 | MUX_TOKEN_ID=xxxx 2 | MUX_TOKEN_SECRET=xxxx 3 | ONEGRAPH_APP_ID=xxxx 4 | -------------------------------------------------------------------------------- /gatsby-example-graphql/gatsby-browser.js: -------------------------------------------------------------------------------- 1 | import "./src/styles/global.css" 2 | 3 | -------------------------------------------------------------------------------- /gatsby-example-graphql/gatsby-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Configure your Gatsby site with this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/gatsby-config/ 5 | */ 6 | 7 | require("dotenv").config({ 8 | path: `.env.${process.env.NODE_ENV}`, 9 | }) 10 | 11 | module.exports = { 12 | /* Your site config here */ 13 | plugins: [ 14 | { 15 | resolve: "gatsby-source-graphql", 16 | options: { 17 | // Arbitrary name for the remote schema Query type 18 | typeName: "OneGraph", 19 | // Field under which the remote schema will be accessible. You'll use this in your Gatsby query 20 | fieldName: "onegraph", 21 | // Url to query from - this is the onegraph Mux API 22 | url: `https://serve.onegraph.com/dynamic?app_id=${process.env.ONEGRAPH_APP_ID}`, 23 | }, 24 | }, 25 | ], 26 | } 27 | -------------------------------------------------------------------------------- /gatsby-example-graphql/gatsby-node.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's Node APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/node-apis/ 5 | */ 6 | 7 | exports.createPages = async function ({ actions, graphql }) { 8 | actions.createPage({ 9 | path: '/', 10 | component: require.resolve('./src/templates/index.js'), 11 | context: { 12 | tokenId: process.env.MUX_TOKEN_ID, 13 | tokenSecret: process.env.MUX_TOKEN_SECRET, 14 | } 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /gatsby-example-graphql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-starter-hello-world", 3 | "private": true, 4 | "description": "A simplified bare-bones starter for Gatsby", 5 | "version": "0.1.0", 6 | "license": "0BSD", 7 | "scripts": { 8 | "build": "gatsby build", 9 | "develop": "gatsby develop", 10 | "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"", 11 | "start": "npm run develop", 12 | "serve": "gatsby serve", 13 | "clean": "gatsby clean", 14 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1", 15 | "dev": "yarn develop" 16 | }, 17 | "dependencies": { 18 | "dotenv": "^8.2.0", 19 | "gatsby": "^2.24.37", 20 | "gatsby-source-graphql": "^2.7.0", 21 | "hls.js": "^0.14.8", 22 | "react": "^16.12.0", 23 | "react-dom": "^16.12.0" 24 | }, 25 | "devDependencies": { 26 | "prettier": "2.0.5" 27 | }, 28 | "repository": { 29 | "type": "git", 30 | "url": "https://github.com/gatsbyjs/gatsby-starter-hello-world" 31 | }, 32 | "bugs": { 33 | "url": "https://github.com/gatsbyjs/gatsby/issues" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /gatsby-example-graphql/src/components/video-player.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable jsx-a11y/media-has-caption */ 2 | 3 | import React, { useEffect, useRef } from 'react' 4 | import Hls from 'hls.js' 5 | 6 | export default function VideoPlayer({ src, poster }) { 7 | const videoRef = useRef(null) 8 | 9 | useEffect(() => { 10 | const video = videoRef.current 11 | if (!video) return 12 | 13 | video.controls = true 14 | let hls 15 | 16 | if (video.canPlayType('application/vnd.apple.mpegurl')) { 17 | // This will run in safari, where HLS is supported natively 18 | video.src = src 19 | } else if (Hls.isSupported()) { 20 | // This will run in all other modern browsers 21 | hls = new Hls() 22 | hls.loadSource(src) 23 | hls.attachMedia(video) 24 | } else { 25 | console.error( 26 | 'This is an old browser that does not support MSE https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API' 27 | ) 28 | } 29 | 30 | return () => { 31 | if (hls) { 32 | hls.destroy() 33 | } 34 | } 35 | }, [src, videoRef]) 36 | 37 | return ( 38 | <> 39 |