Skip to content

Commit

Permalink
Made Audio and Video panes not widgets
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Oct 30, 2019
1 parent d2d2bf0 commit 560658e
Show file tree
Hide file tree
Showing 11 changed files with 439 additions and 28 deletions.
141 changes: 141 additions & 0 deletions examples/reference/panes/Audio.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import panel as pn\n",
"\n",
"pn.extension()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The ``Audio`` widget displays an audio player given a local or remote audio file. The widget also allows access and control over the player state including toggling of playing/``paused`` and ``loop`` state, the current ``time``, and the ``volume``. The audio player supports ``ogg``, ``mp3``, and ``wav`` files.\n",
"\n",
"#### Parameters:\n",
"\n",
"For layout and styling related parameters see the [customization user guide](../../user_guide/Customization.ipynb).\n",
"\n",
"* **``name``** (str): The title of the widget\n",
"* **``loop``** (boolean): Whether to loop when reaching the end of playback\n",
"* **``object``** (string): Local file path or remote URL pointing to audio file\n",
"* **``paused``** (boolean): Whether the player is paused\n",
"* **``throttle``** (int): How frequently to sample the current playback time in milliseconds\n",
"* **``time``** (float): Current playback time in seconds\n",
"* **``volume``** (int): Volume in the range 0-100\n",
"\n",
"___"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `Audio` pane can be constructed with a URL pointing to a remote audio file or a local audio file (in which case the data is embedded)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pn.pane.Audio('http://ccrma.stanford.edu/~jos/mp3/pno-cs.mp3')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Alternatively, if SciPy is available, the Pane may also be constructed from a NumPy array containing int16 values and a `sample_rate`, e.g. in this example we plot a frequency modulated signal:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sps = 44100 # Samples per second\n",
"duration = 10 # Duration in seconds\n",
"\n",
"modulator_frequency = 2.0\n",
"carrier_frequency = 120.0\n",
"modulation_index = 2.0\n",
"\n",
"time = np.arange(sps*duration) / sps\n",
"modulator = np.sin(2.0 * np.pi * modulator_frequency * time) * modulation_index\n",
"carrier = np.sin(2.0 * np.pi * carrier_frequency * time)\n",
"waveform = np.sin(2. * np.pi * (carrier_frequency * time + modulator))\n",
" \n",
"waveform_quiet = waveform * 0.3\n",
"waveform_int = np.int16(waveform_quiet * 32767)\n",
"\n",
"audio = pn.pane.Audio(waveform_int, sample_rate=sps)\n",
"audio"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The player can be controlled using its own widgets, as well as by using Python code as follows. To pause or unpause it in code, use the ``paused`` property:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#audio.paused = False"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The current player ``time`` can be read and set with the time variable (in seconds):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"audio.time"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The ``volume`` may also be read and set:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"audio.volume = 50"
]
}
],
"metadata": {
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
112 changes: 112 additions & 0 deletions examples/reference/panes/Video.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import panel as pn\n",
"\n",
"pn.extension()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The ``Video`` Pane displays a video player given a local or remote video file. The widget also allows access and control over the player state including toggling of playing/``paused`` and ``loop`` state, the current ``time``, and the ``volume``. Depending on the browser the video player supports ``mp4``, ``webm``, and ``ogg`` containers and a variety of codecs.\n",
"\n",
"#### Parameters:\n",
"\n",
"For layout and styling related parameters see the [customization user guide](../../user_guide/Customization.ipynb).\n",
"\n",
"* **``name``** (str): The title of the widget\n",
"* **``loop``** (boolean): Whether to loop when reaching the end of playback\n",
"* **``object``** (string): Local file path or remote URL pointing to audio file\n",
"* **``paused``** (boolean): Whether the player is paused\n",
"* **``throttle``** (int): How frequently to sample the current playback time in milliseconds\n",
"* **``time``** (float): Current playback time in seconds\n",
"* **``volume``** (int): Volume in the range 0-100\n",
"\n",
"___"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `Video` Pane can be constructed with a URL pointing to a remote video file or a local video file (in which case the data is embedded)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"video = pn.pane.Video('https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4',\n",
" width=640, height=480)\n",
"\n",
"video"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The player can be controlled using its own widgets, as well as by using Python code as follows. To pause or unpause it in code, use the ``paused`` property:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#video.paused = False"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The current player ``time`` can be read and set with the time variable (in seconds):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"video.time"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The ``volume`` may also be read and set:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"video.volume = 50"
]
}
],
"metadata": {
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
2 changes: 2 additions & 0 deletions examples/reference/widgets/Audio.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"<div style=\"background-color: lightcoral; width: 100%; border-radius:5px; padding: 10px; color: white\">Warning: The Audio widget is deprecated use the Audio pane instead.</div><br>\n",
"\n",
"The ``Audio`` widget displays an audio player given a local or remote audio file. The widget also allows access and control over the player state including toggling of playing/``paused`` and ``loop`` state, the current ``time``, and the ``volume``. The audio player supports ``ogg``, ``mp3``, and ``wav`` files.\n",
"\n",
"For more information about listening to widget events and laying out widgets refer to the [widgets user guide](../../user_guide/Widgets.ipynb). Alternatively you can learn how to build GUIs by declaring parameters independently of any specific widgets in the [param user guide](../../user_guide/Param.ipynb). To express interactivity entirely using Javascript without the need for a Python server take a look at the [links user guide](../../user_guide/Param.ipynb).\n",
Expand Down
15 changes: 8 additions & 7 deletions panel/models/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ export class AudioView extends WidgetView {
}

render(): void {
if (this.audioEl) {
if (this.audioEl)
return
}
this.audioEl = document.createElement('audio')
this.audioEl.controls = true
this.audioEl.src = this.model.value
Expand All @@ -47,9 +46,8 @@ export class AudioView extends WidgetView {
}

update_time(view: AudioView): void {
if ((Date.now() - view._time) < view.model.throttle) {
if ((Date.now() - view._time) < view.model.throttle)
return
}
view._blocked = true
view.model.time = view.audioEl.currentTime
view._time = Date.now()
Expand All @@ -72,17 +70,20 @@ export class AudioView extends WidgetView {
}

set_volume(): void {
if (this._blocked)
if (this._blocked) {
this._blocked = false
return
if (this.model.volume != null)
}
if (this.model.volume != null) {
this.audioEl.volume = (this.model.volume as number)/100
}
}

set_time(): void {
if (this._blocked)
if (this._blocked) {
this._blocked = false
return
}
this.audioEl.currentTime = this.model.time
}

Expand Down
1 change: 1 addition & 0 deletions panel/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export {Player} from "./player"
export {PlotlyPlot} from "./plotly"
export {State} from "./state"
export {VegaPlot} from "./vega"
export {Video} from "./video"
export {VideoStream} from "./videostream"
export {VTKPlot} from "./vtk"
23 changes: 15 additions & 8 deletions panel/models/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,18 @@ export class VideoView extends WidgetView {
}

render(): void {
if (this.videoEl) {
if (this.videoEl)
return
}
this.videoEl = document.createElement('video')
if (!this.model.sizing_mode || this.model.sizing_mode === 'fixed') {
if (this.model.height)
this.videoEl.height = this.model.height;
if (this.model.width)
this.videoEl.width = this.model.width;
}
this.videoEl.style.objectFit = 'fill'
this.videoEl.style.minWidth = '100%';
this.videoEl.style.minHeight = '100%';
this.videoEl.controls = true
this.videoEl.src = this.model.value
this.videoEl.currentTime = this.model.time
Expand All @@ -47,9 +55,8 @@ export class VideoView extends WidgetView {
}

update_time(view: VideoView): void {
if ((Date.now() - view._time) < view.model.throttle) {
if ((Date.now() - view._time) < view.model.throttle)
return
}
view._blocked = true
view.model.time = view.videoEl.currentTime
view._time = Date.now()
Expand All @@ -72,17 +79,19 @@ export class VideoView extends WidgetView {
}

set_volume(): void {
if (this._blocked)
if (this._blocked) {
this._blocked = false
return
}
if (this.model.volume != null)
this.videoEl.volume = (this.model.volume as number)/100
}

set_time(): void {
if (this._blocked)
if (this._blocked) {
this._blocked = false
return
}
this.videoEl.currentTime = this.model.time
}

Expand Down Expand Up @@ -127,5 +136,3 @@ export abstract class Video extends Widget {
})
}
}

Video.initClass()
3 changes: 2 additions & 1 deletion panel/pane/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@
from __future__ import absolute_import, division, unicode_literals

from ..viewable import Viewable
from .ace import Ace # noqa
from .base import PaneBase, Pane # noqa
from .equation import LaTeX # noqa
from .holoviews import HoloViews # noqa
from .image import GIF, JPG, PNG, SVG # noqa
from .markup import HTML, Markdown, Str # noqa
from .media import Audio, Video # noqa
from .plotly import Plotly # noqa
from .plot import Bokeh, Matplotlib, RGGPlot, YT # noqa
from .vega import Vega # noqa
from .vtk import VTK, VTKVolume # noqa
from .ace import Ace # noqa


def panel(obj, **kwargs):
Expand Down
Loading

0 comments on commit 560658e

Please sign in to comment.