Skip to content
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
c745a98
feat: news player (#1115)
luwes May 7, 2025
c9e97fb
tools: remove production env
luwes May 7, 2025
2aff4bf
tools: add github user to action
luwes May 7, 2025
3548168
cd: fix branch release scripts
luwes May 7, 2025
1b4b632
cd: fix git add command
luwes May 7, 2025
add6332
cd: fix git push command
luwes May 7, 2025
23cfaae
cd: fix @mux/mux-video-ads dependency install
luwes May 7, 2025
8a25700
cd: fix custom dependencies version
luwes May 7, 2025
2a0d0eb
fix: create ads export in mux-video, renaming
luwes May 23, 2025
c8fc634
fix: create @mux/mux-video/base for deduplication
luwes May 27, 2025
e64be8d
fix: lint error
luwes May 27, 2025
562d6a8
fix: add adTagUrl prop to react
luwes May 27, 2025
d3ed393
fix: use @mux/mux-video/base for export
luwes May 27, 2025
3a80ce3
fix: use attr hyphenation & fix mediaadbreak UI
luwes May 29, 2025
bb73b21
feat: add @mux/mux-player-react/news package
luwes Jun 2, 2025
4cecd7d
fix: delete cd-news-player.yml, update docs
luwes Jun 2, 2025
f7c56bc
fix: remove mux-video-element attribute
luwes Jun 2, 2025
8383971
fix: remove console.logs
luwes Jun 2, 2025
fb8f3fc
feat: add adblocker bypass option, expose player props, and condition…
ronalduQualabs May 29, 2025
706da6f
feat: rename ad events to match mux-embed, cleanup
luwes Jun 3, 2025
ca7e3b2
fix: cleanup, add missing ad methods
luwes Jun 3, 2025
081ae2f
feat: add ad events, cleanup ads logic
luwes Jun 10, 2025
4a56807
fix: lint and type issues
luwes Jun 10, 2025
b94d645
fix: Refactor adBreak handling to use internal state
luwes Jun 10, 2025
76b800a
fix: move news theme to mux-player
luwes Jun 10, 2025
61c8e8c
fix: theme issue, improve npm scripts
luwes Jun 10, 2025
bbf353b
feat: isolate ads video mixin, cleanup
luwes Jun 11, 2025
e3f68d5
feat: move resize observer, add more ad events
luwes Jun 11, 2025
4912264
fix: prevent seek and play during ad break
luwes Jun 11, 2025
79d191c
fix: fix props order, add onEnded in news player
luwes Jun 11, 2025
38e5c21
fix: remove storyboard track when adBreak is true
luwes Jun 11, 2025
5420432
fix: add more ad events to react player
luwes Jun 11, 2025
304cc75
fix: remove unneeded div
luwes Jun 12, 2025
8b78620
fix: add dev scripts back in
luwes Jun 12, 2025
c279392
fix: add video api element interface back in
luwes Jun 12, 2025
491636e
feat: isolate ads player logic, fixes and cleanup
luwes Jun 13, 2025
c54b7f4
fix: adsLoader not available, Mux data issue
luwes Jun 13, 2025
c6bf81e
fix: bug where ads played again on adbreakend
luwes Jun 13, 2025
4bd3929
fix: add title to metadata
luwes Jun 13, 2025
6032816
fix: remove non functioning try / catch
luwes Jun 13, 2025
e66ab83
example: Mux player test assets env for Mux data
luwes Jun 13, 2025
8317330
fix: iOS mse track element bug
luwes Jun 14, 2025
b457195
docs: update mux-video readme
luwes Jun 14, 2025
2ae7143
fix: adBreak timing and pause content on start ad
luwes Jun 16, 2025
9ae4ccc
example: fix vanilla ads examples
luwes Jun 17, 2025
9151309
fix: reset state on emptied and destroy
luwes Jun 17, 2025
dbfb96f
Merge branch 'main' into ads-video-mixin
luwes Jun 18, 2025
ef04df9
fix: reset ads when src changes
luwes Jun 18, 2025
1c289f6
fix: ad-tag-url observe, add unload ads
luwes Jun 18, 2025
ccf9270
fix: update example w/ ad-tag-url input
luwes Jun 18, 2025
5c2f133
fix: play freeze on too early destroy ads manager
luwes Jun 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 0 additions & 55 deletions .github/workflows/cd-news-player.yml

This file was deleted.

1 change: 1 addition & 0 deletions examples/nextjs-with-typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@mux/mux-uploader-react": ">=1.0.0-beta.0",
"@mux/mux-video": ">=0.3.0",
"@mux/mux-video-react": ">=0.3.0",
"media-chrome": "^4.9.0",
"next": "^14.2.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
75 changes: 75 additions & 0 deletions examples/nextjs-with-typescript/pages/MuxNewsPlayer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import Head from 'next/head';
import Script from 'next/script';
import { useState } from 'react';
import MuxNewsPlayer from '@mux/mux-player-react/news';

function MuxNewsPlayerPage() {

const relatedVideos = [
{
imageUrl: "https://image.mux.com/DVBhwqkhxkOiLRjUAYJS6mCBJSuC00tB4iWjJmEofJoo/thumbnail.jpg",
title: "Test video title 1",
playbackId: "DVBhwqkhxkOiLRjUAYJS6mCBJSuC00tB4iWjJmEofJoo",
adTagUrl: "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=",
},
{
imageUrl: "https://image.mux.com/VcmKA6aqzIzlg3MayLJDnbF55kX00mds028Z65QxvBYaA/thumbnail.jpg",
title: "Test video title 2",
playbackId: "VcmKA6aqzIzlg3MayLJDnbF55kX00mds028Z65QxvBYaA",
adTagUrl: "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpreonly&ciu_szs=300x250%2C728x90&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&correlator=",
},
{
imageUrl: "https://image.mux.com/gZh02tKCI015W6k2XdYSh4srGnksYvsoT1uHsYOlv4Blo/thumbnail.jpg",
title: "Test video title 3",
playbackId: "gZh02tKCI015W6k2XdYSh4srGnksYvsoT1uHsYOlv4Blo",
adTagUrl: "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpreonlybumper&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&correlator=",
},
];

const [sdkReady, setSdkReady] = useState(false);

return (
<>
<Head>
<title>&lt;Playlist/&gt; Demo 3</title>
</Head>

<Script
src="https://imasdk.googleapis.com/js/sdkloader/ima3.js"
onReady={() => {
setSdkReady(true);
console.log("Google IMA SDK loaded");
}}
onError={() => {
setSdkReady(true);
console.log("Google IMA SDK failed to load");
}}
strategy="afterInteractive"
/>

{sdkReady &&
<MuxNewsPlayer
allowAdBlocker={true}
videoList={relatedVideos}
onAdRequest={() => console.log('Ad Request')}
onAdResponse={() => console.log('Ad Response')}
onAdImpression={() => console.log('Ad Impression')}
onAdBreakStart={() => console.log('Ad Break Start')}
onAdPlay={() => console.log('Ad Play')}
onAdPlaying={() => console.log('Ad Playing')}
onAdPause={() => console.log('Ad Pause')}
onAdFirstQuartile={() => console.log('Ad First Quartile')}
onAdMidpoint={() => console.log('Ad Midpoint')}
onAdThirdQuartile={() => console.log('Ad Third Quartile')}
onAdClick={() => console.log('Ad Click')}
onAdSkip={() => console.log('Ad Skip')}
onAdClose={() => console.log('Ad Close')}
onAdEnded={() => console.log('Ad Ended')}
onAdBreakEnd={() => console.log('Ad Break End')}
onAdError={() => console.log('Ad Error')}
/>}
</>
);
}

export default MuxNewsPlayerPage;
69 changes: 69 additions & 0 deletions examples/nextjs-with-typescript/pages/MuxPlayerAds.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import Script from 'next/script';
import Head from 'next/head';
import { useState } from 'react';
import MuxPlayer from '@mux/mux-player-react/ads';
import NewsTheme from '@mux/mux-player-react/themes/news';

function MuxPlayerAdsPage() {
const [sdkReady, setSdkReady] = useState(false);

return (
<>
<Head>
<title>&lt;MuxPlayer/&gt; (ads) Demo</title>
</Head>

<Script
src="https://imasdk.googleapis.com/js/sdkloader/ima3.js"
onReady={() => {
setSdkReady(true);
console.log("Google IMA SDK loaded");
}}
onError={() => {
setSdkReady(true);
console.log("Google IMA SDK failed to load");
}}
strategy="afterInteractive"
/>

{/*
single preroll skippable
adTagUrl="https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator="

VMAP - Pre-roll Single Ad, Mid-roll Standard Pod with 3 ads, Post-roll Single Ad
adTagUrl="https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpostpod&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator="
*/}

{sdkReady && <MuxPlayer
theme={NewsTheme}
streamType="on-demand"
playbackId="ihZa7qP1zY8oyLSQW9TS602VgwQvNdyIvlk9LInEGU2s"
adTagUrl="https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator="
allowAdBlocker={true}
onAdRequest={() => console.log('Ad Request')}
onAdResponse={() => console.log('Ad Response')}
onAdImpression={() => console.log('Ad Impression')}
onAdBreakStart={() => console.log('Ad Break Start')}
onAdPlay={() => console.log('Ad Play')}
onAdPlaying={() => console.log('Ad Playing')}
onAdPause={() => console.log('Ad Pause')}
onAdFirstQuartile={() => console.log('Ad First Quartile')}
onAdMidpoint={() => console.log('Ad Midpoint')}
onAdThirdQuartile={() => console.log('Ad Third Quartile')}
onAdClick={() => console.log('Ad Click')}
onAdSkip={() => console.log('Ad Skip')}
onAdClose={() => console.log('Ad Close')}
onAdEnded={() => console.log('Ad Ended')}
onAdBreakEnd={() => console.log('Ad Break End')}
onAdError={() => console.log('Ad Error')}
metadata={{
video_id: "video-id-12345",
video_title: "Elephants Dream",
viewer_user_id: "user-id-6789",
}}
/>}
</>
);
}

export default MuxPlayerAdsPage;
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ function MuxPlayerPage() {
onCuePointChange={({ target }) => {
setActiveCuePoint((target as MuxPlayerElement).activeCuePoint);
}}
onCuePointsChange={({ target }) => {
setActiveCuePoint((target as MuxPlayerElement).activeCuePoint);
}}
/>
<div>
<b>Active CuePoint:</b>
Expand Down
22 changes: 22 additions & 0 deletions examples/nextjs-with-typescript/pages/MuxPlayerError.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* eslint-disable @next/next/no-img-element */
import Head from 'next/head';
import MuxPlayer from "@mux/mux-player-react";

function MuxPlayerPage() {
return (
<>
<Head>
<title>&lt;MuxPlayer/&gt; (error) Demo</title>
</Head>

<MuxPlayer
playbackId="ihZa7qP1zY8oyLSQW9TS602VgwQvNdyIvlk9LInEGU2"
onError={(error) => {
console.error('MuxPlayer onError', error);
}}
/>
</>
);
}

export default MuxPlayerPage;
4 changes: 4 additions & 0 deletions examples/nextjs-with-typescript/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ function HomePage() {
<li><Link href="/MuxVideo" className="video">&lt;MuxVideo&gt;</Link></li>
<li><Link href="/MuxAudio"className="audio">&lt;MuxAudio&gt;</Link></li>
<li><Link href='/MuxPlayer?playbackId="ihZa7qP1zY8oyLSQW9TS602VgwQvNdyIvlk9LInEGU2s"' className="player">&lt;MuxPlayer&gt;</Link></li>
<li><Link href="/MuxPlayerAds" className="player"><>&lt;MuxPlayer&gt;<br />(ads)</></Link></li>
<li><Link href="/MuxNewsPlayer" className="player"><>&lt;MuxNewsPlayer&gt;<br />(ads + playlist)</></Link></li>
<li><Link href='/MuxPlayerError' className="player">&lt;MuxPlayer&gt; (error)</Link></li>
<li><Link href="/MuxPlayerPosterSlot" className="player"><>&lt;MuxPlayer&gt;<br/>(poster slot)</></Link></li>
<li><Link href="/MuxPlayerTheme" className="player"><>&lt;MuxPlayer&gt;<br/>(theme)</></Link></li>
<li><Link href="/MuxPlayerCuePoints" className="player"><>&lt;MuxPlayer&gt;<br/>(CuePoints)</></Link></li>
Expand All @@ -24,6 +27,7 @@ function HomePage() {
<li><Link href="/mux-audio" className="audio"><>&lt;mux-audio&gt;<br/>(Web Component)</></Link></li>
<li><Link href="/mux-player" className="player"><>&lt;mux-player&gt;<br/>(Web Component)</></Link></li>
<li><Link href="/mux-video-react" className="video"><>&lt;MuxVideo&gt;<br/>(React Web Component)</></Link></li>
<li><Link href="/mux-video-ads-react" className="video"><>&lt;MuxVideo&gt; (ads)<br />(React Web Component)</></Link></li>
<li><Link href="/app-router" className="react"><>App Router</></Link></li>
</ul>
</nav>
Expand Down
119 changes: 119 additions & 0 deletions examples/nextjs-with-typescript/pages/mux-video-ads-react.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import Head from 'next/head';
import Script from 'next/script';
import { useRef, useState, useEffect } from 'react';
import MuxVideoAds from '@mux/mux-video/ads/react';

function MuxVideoPage() {
const mediaElRef = useRef(null);
const textareaRef = useRef<HTMLTextAreaElement>(null);
const [sdkReady, setSdkReady] = useState(false);
const [eventLogs, setEventLogs] = useState<string[]>([]);

// Function to log events to the textarea
const logEvent = (event: string) => {
const timestamp = new Date().toISOString().substr(11, 12);
setEventLogs(prev => [...prev, `${timestamp} - ${event}`]);
};

// Auto-scroll textarea to bottom when logs update if scrolled
useEffect(() => {
if (textareaRef.current) {
const isScrolledToEnd = textareaRef.current.scrollTop >= textareaRef.current.scrollHeight - textareaRef.current.offsetHeight - 50;
if (isScrolledToEnd) {
textareaRef.current.scrollTop = textareaRef.current.scrollHeight;
}
}
}, [eventLogs]);

// Set up event listeners when video element is available
useEffect(() => {
const videoElement = mediaElRef.current;
if (!videoElement || !sdkReady) return;

const { Events } = (videoElement.constructor as typeof MuxVideoElement);

// Create event handler functions mapped by event name
const eventHandlers = Events.reduce((handlers, eventName) => {
handlers[eventName] = () => logEvent(eventName);
return handlers;
}, {} as Record<string, () => void>);

// Add event listeners
Events.forEach(eventName => {
videoElement.addEventListener(eventName, eventHandlers[eventName]);
});

return () => {
if (!videoElement) return;
// Remove event listeners using the same handler references
Events.forEach(eventName => {
videoElement.removeEventListener(eventName, eventHandlers[eventName]);
});
};
}, [sdkReady]);

return (
<>
<Head>
<title>&lt;MuxVideoAds/&gt; Demo</title>
</Head>

<Script
src="https://imasdk.googleapis.com/js/sdkloader/ima3.js"
onReady={() => {
setSdkReady(true);
logEvent("Google IMA SDK loaded");
}}
onError={() => {
setSdkReady(true);
logEvent("Google IMA SDK failed to load");
}}
strategy="afterInteractive"
/>

{/*
single preroll skippable
adTagUrl="https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator="

single postroll
adTagUrl="https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpostonly&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&correlator="

VMAP - Pre-roll Single Ad, Mid-roll Standard Pod with 3 ads, Post-roll Single Ad
adTagUrl="https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpostpod&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator="
*/}

<div style={{ display: 'flex', flexDirection: 'column', gap: '20px', maxWidth: '800px', margin: '0 auto' }}>
{sdkReady && <MuxVideoAds
ref={mediaElRef}
playbackId="VcmKA6aqzIzlg3MayLJDnbF55kX00mds028Z65QxvBYaA"
controls
playsInline={true}
preferPlayback="mse"
allowAdBlocker={true}
adTagUrl="https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator="
/>}

<div>
<h3>Event Log</h3>
<textarea
ref={textareaRef}
readOnly
value={eventLogs.join('\n')}
style={{
width: '100%',
height: '300px',
fontFamily: 'monospace',
fontSize: '14px',
padding: '8px',
border: '1px solid #ddd',
borderRadius: '4px',
overflowY: 'auto'
}}
/>
</div>
</div>
</>
);
}

export default MuxVideoPage;
1 change: 1 addition & 0 deletions examples/nextjs-with-typescript/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ mux-video:not([audio]),
video {
aspect-ratio: 16 / 9;
background: #000;
overflow: hidden;
}

.component-page {
Expand Down
2 changes: 1 addition & 1 deletion examples/nextjs-with-typescript/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"incremental": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
Expand Down
Loading
Loading