2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-26 10:34:52 +00:00

49_SSCam: V8.0.0, new type "hls" of streaming devices, hls playback now available for all common browsers, tooltip hints in streaming devices, minor fixes

git-svn-id: https://svn.fhem.de/fhem/trunk@17997 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2018-12-17 23:40:00 +00:00
parent e9bda72491
commit 642fa88ae9
3 changed files with 319 additions and 71 deletions

View File

@ -1,5 +1,8 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it. # Do not insert empty lines here, update check depends on it.
- feature: 49_SSCam: V8.0.0, new type "hls" of streaming devices, hls
playback now available for all common browsers,
tooltip hints in streaming devices, minor fixes
- feature: 30_HUEBridge, 31_HUEDevice: added get startup command - feature: 30_HUEBridge, 31_HUEDevice: added get startup command
- change: 55_DWD_OpenData: maintenance release (forum #83097 msg #869647) - change: 55_DWD_OpenData: maintenance release (forum #83097 msg #869647)
- change: mqtt2.template: change name convention + cleanup - change: mqtt2.template: change name convention + cleanup

View File

@ -45,6 +45,7 @@ use HttpUtils;
# Versions History intern # Versions History intern
our %SSCam_vNotesIntern = ( our %SSCam_vNotesIntern = (
"8.0.0" => "13.12.2018 HLS with sscam_hls.js integrated for SSCamSTRM type hls, realize tooltipps in streaming devices, minor fixes",
"7.7.1" => "12.12.2018 change autocreateCams: define new device only if ne device with Internal CAMNAME is defined, ". "7.7.1" => "12.12.2018 change autocreateCams: define new device only if ne device with Internal CAMNAME is defined, ".
"fix getsnapinfo function get wrong snapid or none if cam is new defined ", "fix getsnapinfo function get wrong snapid or none if cam is new defined ",
"7.7.0" => "10.12.2018 SVS-Device: autocreateCams command added, some other fixes and improvements, minor code rewrite, ". "7.7.0" => "10.12.2018 SVS-Device: autocreateCams command added, some other fixes and improvements, minor code rewrite, ".
@ -101,6 +102,8 @@ our %SSCam_vNotesIntern = (
# Versions History extern # Versions History extern
our %SSCam_vNotesExtern = ( our %SSCam_vNotesExtern = (
"8.0.0" => "18.12.2018 HLS is integrated using sscam_hls.js in Streaming device types \"hls\". HLS streaming is now available ".
"for all common used browser types. Tooltipps are added to streaming devices and snapgallery.",
"7.7.0" => "10.12.2018 autocreateCams command added to SVS device. By this command all cameras installed in SVS can be ". "7.7.0" => "10.12.2018 autocreateCams command added to SVS device. By this command all cameras installed in SVS can be ".
"defined automatically. <br>". "defined automatically. <br>".
"In SSCamSTRM devices the \"set &lt;name&gt; popupStream\" command is implemented which may open a popup window with the ". "In SSCamSTRM devices the \"set &lt;name&gt; popupStream\" command is implemented which may open a popup window with the ".
@ -277,6 +280,37 @@ my %SSCam_errlist = (
600 => "Presetname and PresetID not found in Hash", 600 => "Presetname and PresetID not found in Hash",
); );
# Tooltipps Textbausteine (http://www.walterzorn.de/tooltip/tooltip.htm#download), §NAME§ wird durch Kameranamen ersetzt
our %SSCam_ttips_en = (
ttrefresh => "The playback of streaming content of camera of &quot;§NAME§&quot; will be restartet.",
ttrecstart => "Start an endless recording of camera &quot;§NAME§&quot;.<br>You have to stop the recording manually.",
ttrecstop => "Stopp the recording of camera &quot;§NAME§&quot;.",
ttsnap => "Take a snapshot of camera &quot;§NAME§&quot;.",
ttcmdstop => "Stopp playback of camera &quot;§NAME§&quot;",
tthlsreact => "Reactivate HTTP Livestreaming Interface of camera &quot;§NAME§&quot;.<br>The camera is enforced to restart HLS transmission.",
ttmjpegrun => "Playback the MJPEG Livestream of camera &quot;§NAME§&quot;.",
tthlsrun => "Playback the native HTTP Livestream of camera &quot;§NAME§&quot;.",
ttlrrun => "Playback of last recording of camera &quot;§NAME§&quot; in an iFrame.<br>Both MJPEG and H.264 recordings are rendered.",
tth264run => "Playback of last H.264 recording of camera &quot;§NAME§&quot;.<br>It only starts if the recording is type H.264",
ttlmjpegrun => "Playback of last MJPEG recording of camera &quot;§NAME§&quot;.<br>It only starts if the recording is type MJPEG",
ttlsnaprun => "Playback of last snapshot of camera &quot;§NAME§&quot;.",
);
our %SSCam_ttips_de = (
ttrefresh => "Die Wiedergabe des Streams von Kamera &quot;§NAME§&quot; wird neu gestartet.",
ttrecstart => "Startet eine Endlosaufnahme von Kamera &quot;§NAME§&quot;.<br>Die Aufnahme muß manuell gestoppt werden.",
ttrecstop => "Stoppt die laufende Aufnahme von Kamera &quot;§NAME§&quot;.",
ttsnap => "Ein Schnappschuß von Kamera &quot;§NAME§&quot; wird aufgenommen.",
ttcmdstop => "Stopp Wiedergabe von Kamera &quot;§NAME§&quot;",
tthlsreact => "Reactiviert das HTTP Livestreaming Interface von camera &quot;§NAME§&quot;.<br>Die Kamera wird aufgefordert die HLS Übertragung zu restarten.",
ttmjpegrun => "Wiedergabe des MJPEG Livestreams von Kamera &quot;§NAME§&quot;",
tthlsrun => "Wiedergabe des HTTP Livestreams von Kamera &quot;§NAME§&quot;.<br>Es wird die HLS Funktion der Synology Surveillance Station verwendet.",
ttlrrun => "Wiedergabe der letzten Aufnahme von Kamera &quot;§NAME§&quot; in einem iFrame.<br>Es werden sowohl MJPEG als auch H.264 Aufnahmen wiedergegeben.",
tth264run => "Wiedergabe der letzten H.264 Aufnahme von Kamera &quot;§NAME§&quot;.<br>Die Wiedergabe startet nur wenn die Aufnahme vom Typ H.264 ist.",
ttlmjpegrun => "Wiedergabe der letzten MJPEG Aufnahme von Kamera &quot;§NAME§&quot;.<br>Die Wiedergabe startet nur wenn die Aufnahme vom Typ MJPEG ist.",
ttlsnaprun => "Wiedergabe des letzten Schnappschusses von Kamera &quot;§NAME§&quot;.",
);
# Standardvariablen # Standardvariablen
my $SSCam_slim = 3; # default Anzahl der abzurufenden Schnappschüsse mit snapGallery my $SSCam_slim = 3; # default Anzahl der abzurufenden Schnappschüsse mit snapGallery
my $SSCAM_snum = "1,2,3,4,5,6,7,8,9,10"; # mögliche Anzahl der abzurufenden Schnappschüsse mit snapGallery my $SSCAM_snum = "1,2,3,4,5,6,7,8,9,10"; # mögliche Anzahl der abzurufenden Schnappschüsse mit snapGallery
@ -288,6 +322,7 @@ use vars qw($FW_detail); # currently selected device for detail view
use vars qw($FW_wname); # Web instance use vars qw($FW_wname); # Web instance
sub FW_pH(@); # add href sub FW_pH(@); # add href
################################################################
sub SSCam_Initialize($) { sub SSCam_Initialize($) {
my ($hash) = @_; my ($hash) = @_;
$hash->{DefFn} = "SSCam_Define"; $hash->{DefFn} = "SSCam_Define";
@ -304,6 +339,8 @@ sub SSCam_Initialize($) {
$hash->{AttrList} = $hash->{AttrList} =
"disable:1,0 ". "disable:1,0 ".
"genericStrmHtmlTag ". "genericStrmHtmlTag ".
"hlsNetScript:1,0 ".
"hlsStrmObject ".
"httptimeout ". "httptimeout ".
"htmlattr ". "htmlattr ".
"livestreamprefix ". "livestreamprefix ".
@ -454,6 +491,10 @@ sub SSCam_Attr($$$$) {
# $name is device name # $name is device name
# aName and aVal are Attribute name and value # aName and aVal are Attribute name and value
if ($aName =~ /hlsNetScript/ && SSCam_IsModelCam($hash)) {
return " The attribute \"$aName\" is only valid for devices of type \"SVS\"! Please set this attribute in a device of this type.";
}
# dynamisch PTZ-Attribute setzen (wichtig beim Start wenn Reading "DeviceType" nicht gesetzt ist) # dynamisch PTZ-Attribute setzen (wichtig beim Start wenn Reading "DeviceType" nicht gesetzt ist)
if ($cmd eq "set" && ($aName =~ m/ptzPanel_.*/)) { if ($cmd eq "set" && ($aName =~ m/ptzPanel_.*/)) {
foreach my $n (0..9) { foreach my $n (0..9) {
@ -639,7 +680,7 @@ sub SSCam_Set($@) {
"snap:noArg ". "snap:noArg ".
(AttrVal($name, "snapGalleryBoost",0)?(AttrVal($name,"snapGalleryNumber",undef) || AttrVal($name,"snapGalleryBoost",0))?"snapGallery:noArg ":"snapGallery:$SSCAM_snum ":" "). (AttrVal($name, "snapGalleryBoost",0)?(AttrVal($name,"snapGalleryNumber",undef) || AttrVal($name,"snapGalleryBoost",0))?"snapGallery:noArg ":"snapGallery:$SSCAM_snum ":" ").
"createSnapGallery:noArg ". "createSnapGallery:noArg ".
"createStreamDev:generic,mjpeg,switched ". "createStreamDev:generic,hls,mjpeg,switched ".
((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "createPTZcontrol:noArg ": ""). ((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "createPTZcontrol:noArg ": "").
"enable:noArg ". "enable:noArg ".
"disable:noArg ". "disable:noArg ".
@ -754,7 +795,7 @@ sub SSCam_Set($@) {
$sgdev = "SSCamSTRM.$name.snapgallery"; $sgdev = "SSCamSTRM.$name.snapgallery";
$ret = CommandDefine($hash->{CL},"$sgdev SSCamSTRM {SSCam_composegallery('$name','$sgdev','snapgallery')}"); $ret = CommandDefine($hash->{CL},"$sgdev SSCamSTRM {SSCam_composegallery('$name','$sgdev','snapgallery')}");
return $ret if($ret); return $ret if($ret);
my $room = "SnapGallery"; my $room = "SSCam";
$attr{$sgdev}{room} = $room; $attr{$sgdev}{room} = $room;
return "Snapgallery device \"$sgdev\" created and assigned to room \"$room\"."; return "Snapgallery device \"$sgdev\" created and assigned to room \"$room\".";
@ -763,7 +804,7 @@ sub SSCam_Set($@) {
my $ptzcdev = "SSCamSTRM.$name.PTZcontrol"; my $ptzcdev = "SSCamSTRM.$name.PTZcontrol";
my $ret = CommandDefine($hash->{CL},"$ptzcdev SSCamSTRM {SSCam_ptzpanel('$name','$ptzcdev','ptzcontrol')}"); my $ret = CommandDefine($hash->{CL},"$ptzcdev SSCamSTRM {SSCam_ptzpanel('$name','$ptzcdev','ptzcontrol')}");
return $ret if($ret); return $ret if($ret);
my $room = AttrVal($name,"room","PTZcontrol"); my $room = AttrVal($name,"room","SSCam");
$attr{$ptzcdev}{room} = $room; $attr{$ptzcdev}{room} = $room;
$attr{$ptzcdev}{group} = $name."_PTZcontrol"; $attr{$ptzcdev}{group} = $name."_PTZcontrol";
return "PTZ control device \"$ptzcdev\" created and assigned to room \"$room\"."; return "PTZ control device \"$ptzcdev\" created and assigned to room \"$room\".";
@ -782,13 +823,20 @@ sub SSCam_Set($@) {
$ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','generic')}"); $ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','generic')}");
return $ret if($ret); return $ret if($ret);
} }
if($prop =~ /hls/) {
$livedev = "SSCamSTRM.$name.hls";
$ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','hls')}");
return $ret if($ret);
my $c = "The device needs to set attribute \"hlsStrmObject\" in camera device \"$name\" to a valid HLS videostream";
CommandAttr($hash->{CL},"$livedev comment $c");
}
if($prop =~ /switched/) { if($prop =~ /switched/) {
$livedev = "SSCamSTRM.$name.switched"; $livedev = "SSCamSTRM.$name.switched";
$ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','switched')}"); $ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','switched')}");
return $ret if($ret); return $ret if($ret);
} }
my $room = AttrVal($name,"room","Livestream"); my $room = AttrVal($name,"room","SSCam");
$attr{$livedev}{room} = $room; $attr{$livedev}{room} = $room;
return "Livestream device \"$livedev\" created and assigned to room \"$room\"."; return "Livestream device \"$livedev\" created and assigned to room \"$room\".";
@ -802,7 +850,7 @@ sub SSCam_Set($@) {
'< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >'."\n". '< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >'."\n".
'< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >'."\n". '< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >'."\n".
'<%it_server>,<HomeMode<br>On/Off>,<&nbsp;>,<Status>,<&nbsp;>,&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>'."\n". '<%it_server>,<HomeMode<br>On/Off>,<&nbsp;>,<Status>,<&nbsp;>,&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>'."\n".
'TYPE=SSCam:FILTER=MODEL=SVS:HomeModeState,<&nbsp;>,state,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,?!disable,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>'."\n". 'TYPE=SSCam:FILTER=MODEL=SVS:!HomeModeState,<&nbsp;>,state,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,?!disable,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>,<&nbsp;>'."\n".
''; '';
my $ret = CommandDefine($hash->{CL},"$rgdev readingsGroup $rgdef"); my $ret = CommandDefine($hash->{CL},"$rgdev readingsGroup $rgdef");
@ -1423,7 +1471,7 @@ sub SSCam_FWsummaryFn ($$$$) {
if($hash->{HELPER}{RUNVIEW} =~ /live_fw/) { if($hash->{HELPER}{RUNVIEW} =~ /live_fw/) {
if(ReadingsVal($d, "Record", "Stop") eq "Stop") { if(ReadingsVal($d, "Record", "Stop") eq "Stop") {
# Aufnahmebutton endlos Start # Aufnahmebutton endlos Start
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\">$imgrecendless </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\" >$imgrecendless </a>";
} else { } else {
# Aufnahmebutton Stop # Aufnahmebutton Stop
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>";
@ -6211,6 +6259,11 @@ return;
# Funktion für SSCamSTRM-Devices - Kamera Liveview weblink device # Funktion für SSCamSTRM-Devices - Kamera Liveview weblink device
# API: SYNO.SurveillanceStation.VideoStreaming # API: SYNO.SurveillanceStation.VideoStreaming
# Methode: GetLiveViewPath # Methode: GetLiveViewPath
#
# $camname = Name der Kamaera (Parent-Device)
# $strmdev = Name des Streaming-Devices
# $fmt = Streaming Format
#
###################################################################################### ######################################################################################
sub SSCam_StreamDev($$$) { sub SSCam_StreamDev($$$) {
my ($camname,$strmdev,$fmt) = @_; my ($camname,$strmdev,$fmt) = @_;
@ -6273,7 +6326,40 @@ sub SSCam_StreamDev($$$) {
$pws =~ s/"//g if($pws); $pws =~ s/"//g if($pws);
my $StmKey = ReadingsVal($camname,"StmKey",undef); my $StmKey = ReadingsVal($camname,"StmKey",undef);
# Javascript Bibliothek für Tooltips (http://www.walterzorn.de/tooltip/tooltip.htm#download) und Texte
my $calias = $hash->{CAMNAME}; # Alias der Kamera
my $ttjs = "/fhem/pgm2/sscam_tooltip.js";
my ($ttrefresh, $ttrecstart, $ttrecstop, $ttsnap, $ttcmdstop, $tthlsreact, $ttmjpegrun, $tthlsrun, $ttlrrun, $tth264run, $ttlmjpegrun, $ttlsnaprun);
if(AttrVal("global","language","EN") =~ /EN/) {
$ttrefresh = $SSCam_ttips_en{"ttrefresh"}; $ttrefresh =~ s/§NAME§/$calias/g;
$ttrecstart = $SSCam_ttips_en{"ttrecstart"}; $ttrecstart =~ s/§NAME§/$calias/g;
$ttrecstop = $SSCam_ttips_en{"ttrecstop"}; $ttrecstop =~ s/§NAME§/$calias/g;
$ttsnap = $SSCam_ttips_en{"ttsnap"}; $ttsnap =~ s/§NAME§/$calias/g;
$ttcmdstop = $SSCam_ttips_en{"ttcmdstop"}; $ttcmdstop =~ s/§NAME§/$calias/g;
$tthlsreact = $SSCam_ttips_en{"tthlsreact"}; $tthlsreact =~ s/§NAME§/$calias/g;
$ttmjpegrun = $SSCam_ttips_en{"ttmjpegrun"}; $ttmjpegrun =~ s/§NAME§/$calias/g;
$tthlsrun = $SSCam_ttips_en{"tthlsrun"}; $tthlsrun =~ s/§NAME§/$calias/g;
$ttlrrun = $SSCam_ttips_en{"ttlrrun"}; $ttlrrun =~ s/§NAME§/$calias/g;
$tth264run = $SSCam_ttips_en{"tth264run"}; $tth264run =~ s/§NAME§/$calias/g;
$ttlmjpegrun= $SSCam_ttips_en{"ttlmjpegrun"}; $ttlmjpegrun =~ s/§NAME§/$calias/g;
$ttlsnaprun = $SSCam_ttips_en{"ttlsnaprun"}; $ttlsnaprun =~ s/§NAME§/$calias/g;
} else {
$ttrefresh = $SSCam_ttips_de{"ttrefresh"}; $ttrefresh =~ s/§NAME§/$calias/g;
$ttrecstart = $SSCam_ttips_de{"ttrecstart"}; $ttrecstart =~ s/§NAME§/$calias/g;
$ttrecstop = $SSCam_ttips_de{"ttrecstop"}; $ttrecstop =~ s/§NAME§/$calias/g;
$ttsnap = $SSCam_ttips_de{"ttsnap"}; $ttsnap =~ s/§NAME§/$calias/g;
$ttcmdstop = $SSCam_ttips_de{"ttcmdstop"}; $ttcmdstop =~ s/§NAME§/$calias/g;
$tthlsreact = $SSCam_ttips_de{"tthlsreact"}; $tthlsreact =~ s/§NAME§/$calias/g;
$ttmjpegrun = $SSCam_ttips_de{"ttmjpegrun"}; $ttmjpegrun =~ s/§NAME§/$calias/g;
$tthlsrun = $SSCam_ttips_de{"tthlsrun"}; $tthlsrun =~ s/§NAME§/$calias/g;
$ttlrrun = $SSCam_ttips_de{"ttlrrun"}; $ttlrrun =~ s/§NAME§/$calias/g;
$tth264run = $SSCam_ttips_de{"tth264run"}; $tth264run =~ s/§NAME§/$calias/g;
$ttlmjpegrun= $SSCam_ttips_de{"ttlmjpegrun"}; $ttlmjpegrun =~ s/§NAME§/$calias/g;
$ttlsnaprun = $SSCam_ttips_de{"ttlsnaprun"}; $ttlsnaprun =~ s/§NAME§/$calias/g;
}
$ret = ""; $ret = "";
$ret .= "<script type=\"text/javascript\" src=\"$ttjs\"></script>";
$ret .= '<table class="block wide internals">'; $ret .= '<table class="block wide internals">';
$ret .= '<tbody>'; $ret .= '<tbody>';
$ret .= '<tr class="odd">'; $ret .= '<tr class="odd">';
@ -6281,8 +6367,8 @@ sub SSCam_StreamDev($$$) {
if(!$StmKey || ReadingsVal($camname, "Availability", "") ne "enabled" || IsDisabled($camname)) { if(!$StmKey || ReadingsVal($camname, "Availability", "") ne "enabled" || IsDisabled($camname)) {
# Ausgabe bei Fehler # Ausgabe bei Fehler
my $cam = AttrVal($camname, "alias", $camname); my $cam = AttrVal($camname, "alias", $camname);
$cause = !$StmKey?"Cam $cam has no Reading \"StmKey\" set !":"Cam \"$cam\" is disabled"; $cause = !$StmKey?"Camera $cam has no Reading \"StmKey\" set !":"Cam \"$cam\" is disabled";
$cause = "Cam \"$cam\" is disabled" if(IsDisabled($camname)); $cause = "Camera \"$cam\" is disabled" if(IsDisabled($camname));
$ret .= "<td> <br> <b> $cause </b> <br><br></td>"; $ret .= "<td> <br> <b> $cause </b> <br><br></td>";
$ret .= '</tr>'; $ret .= '</tr>';
$ret .= '</tbody>'; $ret .= '</tbody>';
@ -6291,7 +6377,7 @@ sub SSCam_StreamDev($$$) {
return $ret; return $ret;
} }
if($fmt =~ /mjpeg/) { if ($fmt =~ /mjpeg/) {
if($apivideostmsmaxver) { # keine API "SYNO.SurveillanceStation.VideoStream" mehr ab API v2.8 if($apivideostmsmaxver) { # keine API "SYNO.SurveillanceStation.VideoStream" mehr ab API v2.8
$link = "$proto://$serveraddr:$serverport/webapi/$apivideostmspath?api=$apivideostms&version=$apivideostmsmaxver&method=Stream&cameraId=$camid&format=mjpeg&_sid=$sid"; $link = "$proto://$serveraddr:$serverport/webapi/$apivideostmspath?api=$apivideostms&version=$apivideostmsmaxver&method=Stream&cameraId=$camid&format=mjpeg&_sid=$sid";
} elsif ($hash->{HELPER}{STMKEYMJPEGHTTP}) { } elsif ($hash->{HELPER}{STMKEYMJPEGHTTP}) {
@ -6306,12 +6392,12 @@ sub SSCam_StreamDev($$$) {
if(ReadingsVal($camname, "Record", "Stop") eq "Stop") { if(ReadingsVal($camname, "Record", "Stop") eq "Stop") {
# Aufnahmebutton endlos Start # Aufnahmebutton endlos Start
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\">$imgrecendless </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\" onmouseover=\"Tip('$ttrecstart')\" onmouseout=\"UnTip()\">$imgrecendless </a>";
} else { } else {
# Aufnahmebutton Stop # Aufnahmebutton Stop
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\" onmouseover=\"Tip('$ttrecstop')\" onmouseout=\"UnTip()\">$imgrecstop </a>";
} }
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\" onmouseover=\"Tip('$ttsnap')\" onmouseout=\"UnTip()\">$imgdosnap </a>";
$ret .= "</td>"; $ret .= "</td>";
if(AttrVal($camname,"ptzPanel_use",1)) { if(AttrVal($camname,"ptzPanel_use",1)) {
my $ptz_ret = SSCam_ptzpanel($camname); my $ptz_ret = SSCam_ptzpanel($camname);
@ -6329,7 +6415,7 @@ sub SSCam_StreamDev($$$) {
$ret .= "<td></td>" if(AttrVal($camname,"ptzPanel_use",0)); $ret .= "<td></td>" if(AttrVal($camname,"ptzPanel_use",0));
} }
} elsif($fmt =~ /generic/) { } elsif ($fmt =~ /generic/) {
my $htag = AttrVal($camname,"genericStrmHtmlTag",""); my $htag = AttrVal($camname,"genericStrmHtmlTag","");
if( $htag =~ m/^\s*(.*)\s*$/s ) { if( $htag =~ m/^\s*(.*)\s*$/s ) {
$htag = $1; $htag = $1;
@ -6349,23 +6435,23 @@ sub SSCam_StreamDev($$$) {
$ret .= "<td>"; $ret .= "<td>";
$ret .= "$htag"; $ret .= "$htag";
if($htag) { if($htag) {
$streamHash->{HELPER}{STREAM} = "$htag"; # Stream für "get <SSCamSTRM-Device> popupStream" speichern $streamHash->{HELPER}{STREAM} = "$htag"; # Stream für "set <SSCamSTRM-Device> popupStream" speichern
$streamHash->{HELPER}{STREAM} =~ s/["']//g; $streamHash->{HELPER}{STREAM} =~ s/["']//g;
$streamHash->{HELPER}{STREAM} =~ s/\s+/ /g; $streamHash->{HELPER}{STREAM} =~ s/\s+/ /g;
$streamHash->{HELPER}{STREAMACTIVE} = 1; # Statusbit wenn ein Stream aktiviert ist $streamHash->{HELPER}{STREAMACTIVE} = 1; # Statusbit wenn ein Stream aktiviert ist
} }
$ret .= "<br>"; $ret .= "<br>";
Log3($strmdev, 4, "$strmdev - generic Stream params:\n$htag"); Log3($strmdev, 4, "$strmdev - generic Stream params:\n$htag");
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrefresh')\">$imgrefresh </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrefresh')\" onmouseover=\"Tip('$ttrefresh')\" onmouseout=\"UnTip()\">$imgrefresh </a>";
$ret .= $imgblank; $ret .= $imgblank;
if(ReadingsVal($camname, "Record", "Stop") eq "Stop") { if(ReadingsVal($camname, "Record", "Stop") eq "Stop") {
# Aufnahmebutton endlos Start # Aufnahmebutton endlos Start
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\">$imgrecendless </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\" onmouseover=\"Tip('$ttrecstart')\" onmouseout=\"UnTip()\">$imgrecendless </a>";
} else { } else {
# Aufnahmebutton Stop # Aufnahmebutton Stop
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\" onmouseover=\"Tip('$ttrecstop')\" onmouseout=\"UnTip()\">$imgrecstop </a>";
} }
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\" onmouseover=\"Tip('$ttsnap')\" onmouseout=\"UnTip()\">$imgdosnap </a>";
$ret .= "</td>"; $ret .= "</td>";
if(AttrVal($camname,"ptzPanel_use",1)) { if(AttrVal($camname,"ptzPanel_use",1)) {
my $ptz_ret = SSCam_ptzpanel($camname); my $ptz_ret = SSCam_ptzpanel($camname);
@ -6374,26 +6460,72 @@ sub SSCam_StreamDev($$$) {
} }
} }
} elsif($fmt =~ /switched/) { } elsif ($fmt =~ /hls/) {
# es ist ein .m3u8-File bzw. ein Link dorthin zu übergeben
my $cam = AttrVal($camname, "alias", $camname);
my $m3u8 = AttrVal($camname, "hlsStrmObject", "");
if( $m3u8 =~ m/^\s*(.*)\s*$/s ) {
$m3u8 = $1;
$m3u8 =~ s/\$NAME/$camname/g;
}
my $d = $camname;
$d =~ s/\./_/; # Namensableitung zur javascript Codeanpassung
if(!$m3u8) {
$cause = "You have to specify attribute \"hlsStrmObject\" in Camera $cam !";
$ret .= "<td> <br> <b> $cause </b> <br><br></td>";
$ret .= '</tr>';
$ret .= '</tbody>';
$ret .= '</table>';
$ret .= '</div>';
return $ret;
}
$ret .= "<td><video $ha id=video_$d controls autoplay></video><br>";
$ret .= SSCam_bindhlsjs ($camname, $strmdev, $m3u8, $d);
$streamHash->{HELPER}{STREAM} = "<video $pws id=video_$d></video>"; # Stream für "set <SSCamSTRM-Device> popupStream" speichern
$streamHash->{HELPER}{STREAMACTIVE} = 1; # Statusbit wenn ein Stream aktiviert ist
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrefresh')\" onmouseover=\"Tip('$ttrefresh')\" onmouseout=\"UnTip()\">$imgrefresh </a>";
$ret .= $imgblank;
if(ReadingsVal($camname, "Record", "Stop") eq "Stop") {
# Aufnahmebutton endlos Start
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\" onmouseover=\"Tip('$ttrecstart')\" onmouseout=\"UnTip()\">$imgrecendless </a>";
} else {
# Aufnahmebutton Stop
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\" onmouseover=\"Tip('$ttrecstop')\" onmouseout=\"UnTip()\">$imgrecstop </a>";
}
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\" onmouseover=\"Tip('$ttsnap')\" onmouseout=\"UnTip()\">$imgdosnap </a>";
$ret .= "</td>";
if(AttrVal($camname,"ptzPanel_use",1)) {
my $ptz_ret = SSCam_ptzpanel($camname);
if($ptz_ret) {
$ret .= "<td>$ptz_ret</td>";
}
}
} elsif ($fmt =~ /switched/) {
my $wltype = $hash->{HELPER}{WLTYPE}; my $wltype = $hash->{HELPER}{WLTYPE};
$link = $hash->{HELPER}{LINK}; $link = $hash->{HELPER}{LINK};
if($link && $wltype =~ /image|iframe|video|base64img|embed|hls/) { if($link && $wltype =~ /image|iframe|video|base64img|embed|hls/) {
if($wltype =~ /image/) { if($wltype =~ /image/) {
$ret .= "<td><img src=$link $ha onClick=\"FW_okDialog('<img src=$link $pws>')\"><br>" if($link); $ret .= "<td><img src=$link $ha onClick=\"FW_okDialog('<img src=$link $pws>')\"><br>" if($link);
$streamHash->{HELPER}{STREAM} = "<img src=$link $pws>"; # Stream für "get <SSCamSTRM-Device> popupStream" speichern $streamHash->{HELPER}{STREAM} = "<img src=$link $pws>"; # Stream für "set <SSCamSTRM-Device> popupStream" speichern
$streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist $streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\" onmouseover=\"Tip('$ttcmdstop')\" onmouseout=\"UnTip()\">$imgstop </a>";
$ret .= $imgblank; $ret .= $imgblank;
if($hash->{HELPER}{RUNVIEW} =~ /live_fw/) { if($hash->{HELPER}{RUNVIEW} =~ /live_fw/) {
if(ReadingsVal($camname, "Record", "Stop") eq "Stop") { if(ReadingsVal($camname, "Record", "Stop") eq "Stop") {
# Aufnahmebutton endlos Start # Aufnahmebutton endlos Start
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\">$imgrecendless </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\" onmouseover=\"Tip('$ttrecstart')\" onmouseout=\"UnTip()\">$imgrecendless </a>";
} else { } else {
# Aufnahmebutton Stop # Aufnahmebutton Stop
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\" onmouseover=\"Tip('$ttrecstop')\" onmouseout=\"UnTip()\">$imgrecstop </a>";
} }
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\" onmouseover=\"Tip('$ttsnap')\" onmouseout=\"UnTip()\">$imgdosnap </a>";
} }
$ret .= "</td>"; $ret .= "</td>";
if(AttrVal($camname,"ptzPanel_use",1) && $hash->{HELPER}{RUNVIEW} =~ /live_fw/) { if(AttrVal($camname,"ptzPanel_use",1) && $hash->{HELPER}{RUNVIEW} =~ /live_fw/) {
@ -6418,10 +6550,10 @@ sub SSCam_StreamDev($$$) {
</iframe><br>" if($link); </iframe><br>" if($link);
$streamHash->{HELPER}{STREAM} = "<iframe src=$link $pws controls autoplay>". $streamHash->{HELPER}{STREAM} = "<iframe src=$link $pws controls autoplay>".
"Iframes disabled". "Iframes disabled".
"</iframe>"; # Stream für "get <SSCamSTRM-Device> popupStream" speichern "</iframe>"; # Stream für "set <SSCamSTRM-Device> popupStream" speichern
$streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist $streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\" onmouseover=\"Tip('$ttcmdstop')\" onmouseout=\"UnTip()\">$imgstop </a>";
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrefresh')\">$imgrefresh </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrefresh')\" onmouseover=\"Tip('$ttrefresh')\" onmouseout=\"UnTip()\">$imgrefresh </a>";
$ret .= "</td>"; $ret .= "</td>";
if($hash->{HELPER}{AUDIOLINK} && ReadingsVal($camname, "CamAudioType", "Unknown") !~ /Unknown/) { if($hash->{HELPER}{AUDIOLINK} && ReadingsVal($camname, "CamAudioType", "Unknown") !~ /Unknown/) {
$ret .= '</tr>'; $ret .= '</tr>';
@ -6445,9 +6577,9 @@ sub SSCam_StreamDev($$$) {
"<source src=$link type=\"video/ogg\">". "<source src=$link type=\"video/ogg\">".
"<source src=$link type=\"video/webm\">". "<source src=$link type=\"video/webm\">".
"Your browser does not support the video tag". "Your browser does not support the video tag".
"</video>"; # Stream für "get <SSCamSTRM-Device> popupStream" speichern "</video>"; # Stream für "set <SSCamSTRM-Device> popupStream" speichern
$streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist $streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\" onmouseover=\"Tip('$ttcmdstop')\" onmouseout=\"UnTip()\">$imgstop </a>";
$ret .= "</td>"; $ret .= "</td>";
if($hash->{HELPER}{AUDIOLINK} && ReadingsVal($camname, "CamAudioType", "Unknown") !~ /Unknown/) { if($hash->{HELPER}{AUDIOLINK} && ReadingsVal($camname, "CamAudioType", "Unknown") !~ /Unknown/) {
$ret .= '</tr>'; $ret .= '</tr>';
@ -6462,12 +6594,12 @@ sub SSCam_StreamDev($$$) {
$ret .= "<td><img src='data:image/jpeg;base64,$link' $ha onClick=\"FW_okDialog('<img src=data:image/jpeg;base64,$link $pws>')\"><br>" if($link); $ret .= "<td><img src='data:image/jpeg;base64,$link' $ha onClick=\"FW_okDialog('<img src=data:image/jpeg;base64,$link $pws>')\"><br>" if($link);
$streamHash->{HELPER}{STREAM} = "<img src=data:image/jpeg;base64,$link $pws>"; # Stream für "get <SSCamSTRM-Device> popupStream" speichern $streamHash->{HELPER}{STREAM} = "<img src=data:image/jpeg;base64,$link $pws>"; # Stream für "get <SSCamSTRM-Device> popupStream" speichern
$streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist $streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\" onmouseover=\"Tip('$ttcmdstop')\" onmouseout=\"UnTip()\">$imgstop </a>";
$ret .= "</td>"; $ret .= "</td>";
} elsif($wltype =~ /embed/) { } elsif($wltype =~ /embed/) {
$ret .= "<td><embed src=$link $ha onClick=\"FW_okDialog('<img src=$link $pws>')\"></td>" if($link); $ret .= "<td><embed src=$link $ha onClick=\"FW_okDialog('<img src=$link $pws>')\"></td>" if($link);
$streamHash->{HELPER}{STREAM} = "<embed src=$link $pws>"; # Stream für "get <SSCamSTRM-Device> popupStream" speichern $streamHash->{HELPER}{STREAM} = "<embed src=$link $pws>"; # Stream für "set <SSCamSTRM-Device> popupStream" speichern
$streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist $streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist
} elsif($wltype =~ /hls/) { } elsif($wltype =~ /hls/) {
@ -6480,20 +6612,20 @@ sub SSCam_StreamDev($$$) {
"<source src=$link type=\"application/x-mpegURL\">". "<source src=$link type=\"application/x-mpegURL\">".
"<source src=$link type=\"video/MP2T\">". "<source src=$link type=\"video/MP2T\">".
"Your browser does not support the video tag". "Your browser does not support the video tag".
"</video>"; # Stream für "get <SSCamSTRM-Device> popupStream" speichern "</video>"; # Stream für "set <SSCamSTRM-Device> popupStream" speichern
$streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist $streamHash->{HELPER}{STREAMACTIVE} = 1 if($link); # Statusbit wenn ein Stream aktiviert ist
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\" onmouseover=\"Tip('$ttcmdstop')\" onmouseout=\"UnTip()\">$imgstop </a>";
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrefresh')\">$imgrefresh </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrefresh')\" onmouseover=\"Tip('$ttrefresh')\" onmouseout=\"UnTip()\">$imgrefresh </a>";
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdhlsreact')\">$imghlsreact </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdhlsreact')\" onmouseover=\"Tip('$tthlsreact')\" onmouseout=\"UnTip()\">$imghlsreact </a>";
$ret .= $imgblank; $ret .= $imgblank;
if(ReadingsVal($camname, "Record", "Stop") eq "Stop") { if(ReadingsVal($camname, "Record", "Stop") eq "Stop") {
# Aufnahmebutton endlos Start # Aufnahmebutton endlos Start
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\">$imgrecendless </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\" onmouseover=\"Tip('$ttrecstart')\" onmouseout=\"UnTip()\">$imgrecendless </a>";
} else { } else {
# Aufnahmebutton Stop # Aufnahmebutton Stop
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\" onmouseover=\"Tip('$ttrecstop')\" onmouseout=\"UnTip()\">$imgrecstop </a>";
} }
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\" onmouseover=\"Tip('$ttsnap')\" onmouseout=\"UnTip()\">$imgdosnap </a>";
$ret .= "</td>"; $ret .= "</td>";
if(AttrVal($camname,"ptzPanel_use",1)) { if(AttrVal($camname,"ptzPanel_use",1)) {
my $ptz_ret = SSCam_ptzpanel($camname); my $ptz_ret = SSCam_ptzpanel($camname);
@ -6501,17 +6633,19 @@ sub SSCam_StreamDev($$$) {
$ret .= "<td>$ptz_ret</td>"; $ret .= "<td>$ptz_ret</td>";
} }
} }
} }
} else { } else {
my $cam = AttrVal($camname, "alias", $camname); my $cam = AttrVal($camname, "alias", $camname);
$cause = "Playback cam \"$cam\" switched off"; $cause = "Playback cam \"$cam\" switched off";
$ret .= "<td> <br> <b> $cause </b> <br><br>"; $ret .= "<td> <br> <b> $cause </b> <br><br>";
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdmjpegrun')\">$imgmjpegrun </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdmjpegrun')\" onmouseover=\"Tip('$ttmjpegrun')\" onmouseout=\"UnTip()\">$imgmjpegrun </a>";
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdhlsrun')\">$imghlsrun </a>" if(SSCam_IsHLSCap($hash)); $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdhlsrun')\" onmouseover=\"Tip('$tthlsrun')\" onmouseout=\"UnTip()\">$imghlsrun </a>" if(SSCam_IsHLSCap($hash));
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlrirun')\">$imglrirun </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlrirun')\" onmouseover=\"Tip('$ttlrrun')\" onmouseout=\"UnTip()\">$imglrirun </a>";
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlh264run')\">$imglh264run </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlh264run')\" onmouseover=\"Tip('$tth264run')\" onmouseout=\"UnTip()\">$imglh264run </a>";
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlmjpegrun')\">$imglmjpegrun </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlmjpegrun')\" onmouseover=\"Tip('$ttlmjpegrun')\" onmouseout=\"UnTip()\">$imglmjpegrun </a>";
$ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlsnaprun')\">$imglsnaprun </a>"; $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlsnaprun')\" onmouseover=\"Tip('$ttlsnaprun')\" onmouseout=\"UnTip()\">$imglsnaprun </a>";
$ret .= "</td>"; $ret .= "</td>";
} }
} else { } else {
@ -6527,6 +6661,52 @@ sub SSCam_StreamDev($$$) {
return $ret; return $ret;
} }
#############################################################################################
# hls.js laden für Streamimgdevice Typen HLS, RTSP
# $m3u8 - ein .m3u8-File oder ein entsprechender Link
# $d - ein Unique-Name zur Codeableitung (darf keinen . enthalten)
#############################################################################################
sub SSCam_bindhlsjs ($$$$) {
my ($camname, $strmdev, $m3u8, $d) = @_;
my $hlsjs = "sscam_hls.js"; # hls.js Release von Projekteite https://github.com/video-dev/hls.js/releases
my $ret;
$ret .= "<meta charset=\"utf-8\"/>
<!--script src=\"https://cdn.jsdelivr.net/npm/hls.js\@latest\"></script-->
";
my $dcs = (devspec2array("TYPE=SSCam:FILTER=MODEL=SVS"))[0]; # ist ein SVS-Device angelegt ?
my $uns = AttrVal($dcs,"hlsNetScript",0) if($dcs); # ist in einem SVS Device die Nutzung hls.js auf Projektseite ausgewählt ?
if($uns) {
my $lib = "https://cdn.jsdelivr.net/npm/hls.js\@latest";
$ret .= "<script src=\"$lib\"></script>";
Log3($strmdev, 4, "$strmdev - HLS Streaming use net library \"$lib\" ");
} else {
$ret .= "<script type=\"text/javascript\" src=\"/fhem/pgm2/$hlsjs\"></script>";
Log3($strmdev, 4, "$strmdev - HLS Streaming use local file \"/fhem/pgm2/$hlsjs\" ");
}
$ret .= "<script>
if (Hls.isSupported()) {
var video_$d = document.getElementById('video_$d');
var hls = new Hls();
// bind them together
hls.attachMedia(video_$d);
hls.on(Hls.Events.MEDIA_ATTACHED, function () {
console.log(\"video and hls.js are now bound together !\");
hls.loadSource(\"$m3u8\");
hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
console.log(\"manifest loaded, found \" + data.levels.length + \" quality level\");
video_$d.play();
});
});
}
</script>";
return $ret;
}
############################################################################### ###############################################################################
# Schnappschußgalerie zusammenstellen # Schnappschußgalerie zusammenstellen
# Verwendung durch SSCamSTRM-Devices # Verwendung durch SSCamSTRM-Devices
@ -6575,6 +6755,15 @@ sub SSCam_composegallery ($;$$) {
$sgbnote = "<b>ACHTUNG</b> - Es können keine Schnappschüsse abgerufen werden. Bitte setzen sie das Attribut \"snapGalleryBoost=1\" im Device <a href=\"/fhem?detail=$name\">$name</a>" if ($lang eq "DE"); $sgbnote = "<b>ACHTUNG</b> - Es können keine Schnappschüsse abgerufen werden. Bitte setzen sie das Attribut \"snapGalleryBoost=1\" im Device <a href=\"/fhem?detail=$name\">$name</a>" if ($lang eq "DE");
} }
# Javascript Bibliothek für Tooltips (http://www.walterzorn.de/tooltip/tooltip.htm#download) und Texte
my $ttjs = "/fhem/pgm2/sscam_tooltip.js";
my ($ttsnap);
if(AttrVal("global","language","EN") =~ /EN/) {
$ttsnap = $SSCam_ttips_en{"ttsnap"}; $ttsnap =~ s/§NAME§/$camname/g;
} else {
$ttsnap = $SSCam_ttips_de{"ttsnap"}; $ttsnap =~ s/§NAME§/$camname/g;
}
my $header; my $header;
if ($lang eq "EN") { if ($lang eq "EN") {
$header = "Snapshots ($limit/$totalcnt) of camera <b>$camname</b> - newest Snapshot: $lss<br>"; $header = "Snapshots ($limit/$totalcnt) of camera <b>$camname</b> - newest Snapshot: $lss<br>";
@ -6586,11 +6775,12 @@ sub SSCam_composegallery ($;$$) {
$header .= $sgbnote; $header .= $sgbnote;
my $gattr = (AttrVal($name,"snapGallerySize","Icon") eq "Full")?$ha:" "; my $gattr = (AttrVal($name,"snapGallerySize","Icon") eq "Full")?$ha:" ";
my @as = sort{$a <=>$b}keys%{$allsnaps}; my @as = sort{$a<=>$b}keys%{$allsnaps};
# Ausgabetabelle erstellen # Ausgabetabelle erstellen
my ($htmlCode,$ct); my ($htmlCode,$ct);
$htmlCode = "<html>"; $htmlCode = "<html>";
$htmlCode .= "<script type=\"text/javascript\" src=\"$ttjs\"></script>";
$htmlCode .= sprintf("$devWlink <div class=\"makeTable wide\"; style=\"text-align:center\"> $header <br>"); $htmlCode .= sprintf("$devWlink <div class=\"makeTable wide\"; style=\"text-align:center\"> $header <br>");
$htmlCode .= "<table class=\"block wide internals\">"; $htmlCode .= "<table class=\"block wide internals\">";
$htmlCode .= "<tbody>"; $htmlCode .= "<tbody>";
@ -6599,8 +6789,9 @@ sub SSCam_composegallery ($;$$) {
foreach my $key (@as) { foreach my $key (@as) {
$ct = $allsnaps->{$key}{createdTm}; $ct = $allsnaps->{$key}{createdTm};
my $html = sprintf("<td>$ct<br> <img src=\"data:image/jpeg;base64,$allsnaps->{$key}{imageData}\" $gattr onClick=\"FW_okDialog('<img src=data:image/jpeg;base64,$allsnaps->{$key}{imageData} $pws>')\"> </td>" ); my $idata = "";
$idata = "onClick=\"FW_okDialog('<img src=data:image/jpeg;base64,$allsnaps->{$key}{imageData} $pws>')\"" if(AttrVal($name,"snapGalleryBoost",0));
my $html = sprintf("<td>$ct<br> <img src=\"data:image/jpeg;base64,$allsnaps->{$key}{imageData}\" $gattr $idata> </td>" );
$cell++; $cell++;
if ( $cell == $sgc+1 ) { if ( $cell == $sgc+1 ) {
@ -6621,7 +6812,7 @@ sub SSCam_composegallery ($;$$) {
$htmlCode .= "</tbody>"; $htmlCode .= "</tbody>";
$htmlCode .= "</table>"; $htmlCode .= "</table>";
$htmlCode .= "</div>"; $htmlCode .= "</div>";
$htmlCode .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>" if($strmdev); $htmlCode .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\" onmouseover=\"Tip('$ttsnap')\" onmouseout=\"UnTip()\">$imgdosnap </a>" if($strmdev);
$htmlCode .= "</html>"; $htmlCode .= "</html>";
return $htmlCode; return $htmlCode;
@ -7001,8 +7192,8 @@ attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
<ul> <ul>
<li><b> set &lt;name&gt; createPTZcontrol </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for PTZ-CAM)</li> <br> <li><b> set &lt;name&gt; createPTZcontrol </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for PTZ-CAM)</li> <br>
A separate PTZ-control panel will be created (type SSCamSTRM). The current room of the parent camera device is A separate PTZ control panel will be created (type SSCamSTRM). The current room of the parent camera device is
assigned if it is set there. assigned if it is set there (default "SSCam").
With the "ptzPanel_.*"-<a href="#SSCamattr">attributes</a> or respectively the specific attributes of the SSCamSTRM-device With the "ptzPanel_.*"-<a href="#SSCamattr">attributes</a> or respectively the specific attributes of the SSCamSTRM-device
the properties of the control panel can be affected. <br> the properties of the control panel can be affected. <br>
<br><br> <br><br>
@ -7022,7 +7213,7 @@ attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
<li><b> set &lt;name&gt; createSnapGallery </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br> <li><b> set &lt;name&gt; createSnapGallery </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
A snapshot gallery will be created as a separate device (type SSCamSTRM). The device will be provided in A snapshot gallery will be created as a separate device (type SSCamSTRM). The device will be provided in
room "SnapGallery". room "SSCam".
With the "snapGallery..."-<a href="#SSCamattr">attributes</a> respectively the specific attributes of the SSCamSTRM-device With the "snapGallery..."-<a href="#SSCamattr">attributes</a> respectively the specific attributes of the SSCamSTRM-device
you are able to manipulate the properties of the new snapshot gallery device. you are able to manipulate the properties of the new snapshot gallery device.
<br><br> <br><br>
@ -8331,7 +8522,7 @@ attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
<ul> <ul>
<a name="SSCamcreateStreamDev"></a> <a name="SSCamcreateStreamDev"></a>
<li><b> set &lt;name&gt; createStreamDev [generic | mjpeg | switched] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br> <li><b> set &lt;name&gt; createStreamDev [generic | hls | mjpeg | switched] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
Es wird ein separates Streaming-Device (Typ SSCamSTRM) erstellt. Dieses Device kann z.B. als separates Device Es wird ein separates Streaming-Device (Typ SSCamSTRM) erstellt. Dieses Device kann z.B. als separates Device
in einem Dashboard genutzt werden. in einem Dashboard genutzt werden.
@ -8342,6 +8533,7 @@ attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
<table> <table>
<colgroup> <col width=10%> <col width=90%> </colgroup> <colgroup> <col width=10%> <col width=90%> </colgroup>
<tr><td>generic </td><td>- das Streaming-Device gibt einen durch das Attribut "genericStrmHtmlTag" bestimmten Content wieder </td></tr> <tr><td>generic </td><td>- das Streaming-Device gibt einen durch das Attribut "genericStrmHtmlTag" bestimmten Content wieder </td></tr>
<tr><td>hls </td><td>- das Streaming-Device gibt einen permanenten HLS Datenstrom wieder </td></tr>
<tr><td>mjpeg </td><td>- das Streaming-Device gibt einen permanenten MJPEG Kamerastream wieder (Streamkey Methode) </td></tr> <tr><td>mjpeg </td><td>- das Streaming-Device gibt einen permanenten MJPEG Kamerastream wieder (Streamkey Methode) </td></tr>
<tr><td>switched </td><td>- Wiedergabe unterschiedlicher Streamtypen. Drucktasten zur Steuerung werden angeboten. </td></tr> <tr><td>switched </td><td>- Wiedergabe unterschiedlicher Streamtypen. Drucktasten zur Steuerung werden angeboten. </td></tr>
</table> </table>
@ -8349,12 +8541,29 @@ attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
<br><br> <br><br>
Die Gestaltung kann durch HTML-Tags im <a href="#SSCamattr">Attribut</a> "htmlattr" im Kameradevice oder mit den Die Gestaltung kann durch HTML-Tags im <a href="#SSCamattr">Attribut</a> "htmlattr" im Kameradevice oder mit den
spezifischen Attributen im Streaming-Device beeinflusst werden. <br> spezifischen Attributen im Streaming-Device beeinflusst werden. <br><br>
Soll ein HLS-Stream im Streaming-Device vom Typ "switched" gestartet werden, muss die Kamera in der Synology Surveillance Station
auf das Videoformat H.264 eingestellt und HLS von der eingesetzten SVS-Version unterstützt sein. <b>Streaming Device "hls"</b> <br><br>
Diese Auswahltaste wird deshalb im nur im Streaming-Device angeboten wenn das Reading "CamStreamFormat = HLS" beinhaltet. <br>
HLS (HTTP Live Streaming) kann momentan nur auf Mac Safari oder mobilen iOS/Android-Geräten wiedergegeben werden. <br> Das Streaming-Device vom Typ "hls" verwendet die Bibliothek hls.js zur Bildverarbeitung und ist auf allen Browsern mit
Im "switched"-Device werden Drucktasten zur Steuerung des zu startenden Medientyps angeboten. <br> MediaSource extensions (MSE) lauffähig. Mit dem <a href="#SSCamattr">Attribut</a> "hlsNetScript" kann bestimmt werden, ob
die lokal installierte hls.js (./www/pgm2/hls.js) oder immer die aktuellste Bibliotheksversion von der hls.js Projektseite
verwendet werden soll. Dieses Attribut ist zentral in einem Device vom Typ "SVS" zu setzen ! <br>
Bei Verwendung dieses Streamingdevices ist zwingend das <a href="#SSCamattr">Attribut</a> "hlsStrmObject" im SSCam Device
mit dem darzustellenden Stream anzugeben.
<br><br>
<b>Streaming Device "switched hls"</b> <br><br>
Dieser Typ nutzt den von der Synology Surveillance Station gelieferten HLS Videostream.
Soll ein HLS-Stream im Streaming-Device vom Typ "switched" gestartet werden, muss die Kamera in der Synology Surveillance
Station auf das Videoformat H.264 eingestellt und HLS von der eingesetzten SVS-Version unterstützt sein.
Diese Auswahltaste wird deshalb im nur dann im Streaming-Device angeboten, wenn das Reading "CamStreamFormat = HLS" beinhaltet. <br>
HLS (HTTP Live Streaming) kann momentan nur auf Mac Safari oder mobilen iOS/Android-Geräten wiedergegeben werden.
<br><br>
<b>Streaming Device "generic"</b> <br><br>
Ein Streaming-Device vom Typ "generic" benötigt die Angabe von HTML-Tags im Attribut "genericStrmHtmlTag". Diese Tags Ein Streaming-Device vom Typ "generic" benötigt die Angabe von HTML-Tags im Attribut "genericStrmHtmlTag". Diese Tags
spezifizieren den wiederzugebenden Content. <br><br> spezifizieren den wiederzugebenden Content. <br><br>
@ -8374,7 +8583,7 @@ attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
<li><b> set &lt;name&gt; createPTZcontrol </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für PTZ-CAM)</li> <br> <li><b> set &lt;name&gt; createPTZcontrol </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für PTZ-CAM)</li> <br>
Es wird ein separates PTZ-Steuerungspaneel (Type SSCamSTRM) erstellt. Es wird der aktuelle Raum des Kameradevice Es wird ein separates PTZ-Steuerungspaneel (Type SSCamSTRM) erstellt. Es wird der aktuelle Raum des Kameradevice
zugewiesen sofern dort gesetzt. zugewiesen sofern dort gesetzt (default "SSCam").
Mit den "ptzPanel_.*"-<a href="#SSCamattr">Attributen</a> bzw. den spezifischen Attributen des erzeugten Mit den "ptzPanel_.*"-<a href="#SSCamattr">Attributen</a> bzw. den spezifischen Attributen des erzeugten
SSCamSTRM-Devices können die Eigenschaften des PTZ-Paneels beeinflusst werden. <br> SSCamSTRM-Devices können die Eigenschaften des PTZ-Paneels beeinflusst werden. <br>
<br><br> <br><br>
@ -8393,7 +8602,7 @@ attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
<li><b> set &lt;name&gt; createSnapGallery </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br> <li><b> set &lt;name&gt; createSnapGallery </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
Es wird eine Schnappschußgallerie als separates Device (Type SSCamSTRM) erzeugt. Das Device wird im Raum Es wird eine Schnappschußgallerie als separates Device (Type SSCamSTRM) erzeugt. Das Device wird im Raum
"SnapGallery" erstellt. "SSCam" erstellt.
Mit den "snapGallery..."-<a href="#SSCamattr">Attributen</a> bzw. den spezifischen Attributen des erzeugten SSCamSTRM-Devices Mit den "snapGallery..."-<a href="#SSCamattr">Attributen</a> bzw. den spezifischen Attributen des erzeugten SSCamSTRM-Devices
können die Eigenschaften der Schnappschußgallerie beeinflusst werden. können die Eigenschaften der Schnappschußgallerie beeinflusst werden.
<br><br> <br><br>
@ -9178,6 +9387,36 @@ attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
Timeout-Wert für HTTP-Aufrufe zur Synology Surveillance Station, Default: 4 Sekunden (wenn Timeout-Wert für HTTP-Aufrufe zur Synology Surveillance Station, Default: 4 Sekunden (wenn
httptimeout = "0" oder nicht gesetzt) </li><br> httptimeout = "0" oder nicht gesetzt) </li><br>
<a name="hlsNetScript"></a>
<li><b>hlsNetScript</b> &nbsp;&nbsp;&nbsp;&nbsp;(setzbar in Device Typ "SVS") <br>
Wenn gesetzt, wird die aktuellste hls.js Version von der Projektseite verwendet (Internetverbindung nötig).
<br>
Im Standard wird die lokal installierte Version (./www/pgm2/sscam_hls.js) zur Wiedergabe von Daten in allen
Streaming Devices vom Typ "hls" genutzt (siehe set &lt;name&gt; createStreamDev hls").
Dieses Attribut wird in einem Device vom Typ "SVS" gesetzt und gilt zentral für alle Streaming Devices !
</li><br>
<a name="hlsStrmObject"></a>
<li><b>hlsStrmObject</b><br>
Wurde ein Streaming Device mit "set &lt;name&gt; createStreamDev hls" definiert, muss mit diesem Attribut der Link zum
Wiedergabeobjekt bekannt gemacht werden. <br>
Die Angabe muss ein HTTP Live Streaming Objekt mit der Endung ".m3u8" enthalten. <br>
Die Variable $NAME kann als Platzhalter genutzt werden und übernimmt den SSCam-Devicenamen.
<br><br>
<ul>
<b>Beispiele:</b><br>
attr &lt;name&gt; hlsStrmObject https://video-dev.github.io/streams/x36xhzz/x36xhzz.m3u8 <br>
# ein Beispielstream der zum Test des Streaming Devices verwendet werden kann (Internetverbindung nötig) <br><br>
attr &lt;name&gt; hlsStrmObject http://192.168.2.10:32000/CamHE1.m3u8 <br>
# Wiedergabe eines Kamera HLS-Streams der z.B. durch ffmpeg bereitgestellt wird <br><br>
attr &lt;name&gt; hlsStrmObject http://192.168.2.10:32000/$NAME.m3u8 <br>
# Wie obiges Beispiel mit der Variablennutzung für "CamHE1"
</ul>
<br>
</li>
<a name="htmlattr"></a> <a name="htmlattr"></a>
<li><b>htmlattr</b><br> <li><b>htmlattr</b><br>
ergänzende Angaben zur Inline-Bilddarstellung um das Verhalten wie Bildgröße zu beeinflussen. <br><br> ergänzende Angaben zur Inline-Bilddarstellung um das Verhalten wie Bildgröße zu beeinflussen. <br><br>

View File

@ -34,6 +34,7 @@ use warnings;
# Versions History intern # Versions History intern
our %SSCamSTRM_vNotesIntern = ( our %SSCamSTRM_vNotesIntern = (
"2.2.0" => "13.12.2018 load sscam_hls.js, sscam_tooltip.js from pgm2 for HLS Streaming support and tooltips ",
"2.1.0" => "11.12.2018 switch \"popupStream\" from get to set ", "2.1.0" => "11.12.2018 switch \"popupStream\" from get to set ",
"2.0.0" => "09.12.2018 get command \"popupStream\" and attribute \"popupStreamFW\" ", "2.0.0" => "09.12.2018 get command \"popupStream\" and attribute \"popupStreamFW\" ",
"1.5.0" => "02.12.2018 new attribute \"popupWindowSize\" ", "1.5.0" => "02.12.2018 new attribute \"popupWindowSize\" ",
@ -59,6 +60,8 @@ sub SSCam_ptzpanel($;$$);
sub SSCam_StreamDev($$$); sub SSCam_StreamDev($$$);
sub SSCam_getclhash($;$$); sub SSCam_getclhash($;$$);
# my $hlsjs = "hls.js"; # hls.js Release von Seite https://github.com/video-dev/hls.js/releases
################################################################ ################################################################
sub SSCamSTRM_Initialize($) { sub SSCamSTRM_Initialize($) {
my ($hash) = @_; my ($hash) = @_;
@ -83,8 +86,11 @@ sub SSCamSTRM_Initialize($) {
$hash->{FW_hideDisplayName} = 1; # Forum 88667 $hash->{FW_hideDisplayName} = 1; # Forum 88667
# $hash->{FW_addDetailToSummary} = 1; # $hash->{FW_addDetailToSummary} = 1;
# $hash->{FW_atPageEnd} = 1; # wenn 1 -> kein Longpoll ohne informid in HTML-Tag # $hash->{FW_atPageEnd} = 1; # wenn 1 -> kein Longpoll ohne informid in HTML-Tag
}
#$data{FWEXT}{SSCAMSTRM}{SCRIPT} = "/pgm2/".$hlsjs if (!$data{FWEXT}{SSCAMSTRM}{SCRIPT});
return undef;
}
################################################################ ################################################################
sub SSCamSTRM_Define($$) { sub SSCamSTRM_Define($$) {
@ -480,7 +486,7 @@ Abhängig vom Zustand des Streaming-Devices werden zum Start von Aktionen unters
<a name="autoRefresh"></a> <a name="autoRefresh"></a>
<li><b>autoRefresh</b><br> <li><b>autoRefresh</b><br>
Wenn gesetzt, werden aktive Browserseiten des FHEMWEB-Devices welches das SSCamSTRM-Device aufgerufen hat, nach der Wenn gesetzt, werden aktive Browserseiten des FHEMWEB-Devices welches das SSCamSTRM-Device aufgerufen hat, nach der
eingestellten Zeit (Sekunden) neu geladen. Sollen statt dessen Broserseiten eines bestimmten FHEMWEB-Devices neu eingestellten Zeit (Sekunden) neu geladen. Sollen statt dessen Browserseiten eines bestimmten FHEMWEB-Devices neu
geladen werden, kann dieses Device mit dem Attribut "autoRefreshFW" festgelegt werden. geladen werden, kann dieses Device mit dem Attribut "autoRefreshFW" festgelegt werden.
Dies kann in manchen Fällen die Wiedergabe innerhalb einer Anwendung stabilisieren. Dies kann in manchen Fällen die Wiedergabe innerhalb einer Anwendung stabilisieren.
</li> </li>