Skip to content

Commit

Permalink
amcrest: send audio to camera
Browse files Browse the repository at this point in the history
This is initial commit to enable users send audio to cameras with:
  --play-wav
  --audio-send-stream

See man pages for details

Special Thanks to David Adamson for opening this request and
sending his tests.
  • Loading branch information
dougsland committed Mar 20, 2017
1 parent 60e9592 commit 2568607
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 0 deletions.
26 changes: 26 additions & 0 deletions cli/amcrest-cli
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,10 @@ def main():
help='scan Amcrest cameras in the subnet provided\n'
'i.e: 192.168.1.0/24')

parser.add_argument('--play-wav',
dest='play_wav',
help='play wav files')

parser.add_argument('--timeout',
dest='timeout',
type=int,
Expand Down Expand Up @@ -465,6 +469,12 @@ def main():
metavar='httptype channel timercapture',
nargs='+',
help='capture audio stream')

parser.add_argument('--audio-send-stream',
dest='audio_send_stream',
metavar='httptype channel filename',
nargs='+',
help='send audio stream')
# FIXME:
# parser.add_argument('--log-show',
# help='show logs <start time> <end time>')
Expand Down Expand Up @@ -550,6 +560,19 @@ def main():
print((camera.shutdown()))
return

elif args.audio_send_stream:
if len(args.audio_send_stream) <= 3:
print("Requires arguments: httptype, channel, filename, codec")
sys.exit(-1)

httptype = args.audio_send_stream[0]
channel = args.audio_send_stream[1]
filename = args.audio_send_stream[2]
codec = args.audio_send_stream[3]

camera.audio_send_stream(httptype, channel, filename, codec)
return

elif args.audio_stream_capture:
if not args.save:
print("This option requires --save")
Expand All @@ -571,6 +594,9 @@ def main():
else:
camera.audio_stream_capture(httptype, channel)

elif args.play_wav:
return(camera.play_wav(path_file=args.play_wav))

elif args.wlan_config:
print((camera.wlan_config))
return
Expand Down
15 changes: 15 additions & 0 deletions man/amcrest-cli.1
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,12 @@ show record capability
.B --record-config
show record config
.TP
.B --play-wav
play a wav file in the camera microphone
.TP
.B --audio-send-stream
play audio into the camera microphone, user must specify httptype, channel, file and codec
.TP
.B --factory-create
create a media file finder
.TP
Expand Down Expand Up @@ -376,6 +382,15 @@ $ amcrest-cli -H 192.168.1.10 -u admin -p password --ntp-config NTP.Enable=true
$ amcrest-cli -H 192.168.1.10 -u admin -p password --ptz-goto-preset 0 1
.br
$ amcrest-cli --camera mycamera1 --ptz-goto-preset 0 1
.TP
.B Play wav file
$ amcrest-cli -H 192.168.1.10 -u admin -p password --play-wav /path/file.wav
.br
.TP
.B Play audio stream
$ amcrest-cli -H 192.168.1.10 -u admin -p password --audio-send-stream singlepart 1 /path/file.wav G.711A
.br

.SH BUGS
Report bugs to <https://github.com/tchellomello/python-amcrest/issues>
.SH "SEE ALSO"
Expand Down
58 changes: 58 additions & 0 deletions src/amcrest/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,64 @@ def audio_output_channels_numbers(self):
)
return ret.content.decode('utf-8')

def play_wav(self, httptype=None, channel=None,
path_file=None):

if httptype is None:
httptype = 'singlepart'

if channel is None:
channel = '1'

if path_file is None:
raise RuntimeError('filename is required')

self.audio_send_stream(httptype, channel, path_file, 'G.711A')

def audio_send_stream(self, httptype=None,
channel=None, path_file=None, encode=None):
"""
Params:
path_file - path to audio file
channel: - integer
httptype - type string (singlepart or multipart)
singlepart: HTTP content is a continuos flow of audio packets
multipart: HTTP content type is multipart/x-mixed-replace, and
each audio packet ends with a boundary string
Supported audio encode type according with documentation:
PCM
ADPCM
G.711A
G.711.Mu
G.726
G.729
MPEG2
AMR
AAC
"""
if httptype is None or channel is None:
raise RuntimeError("Requires htttype and channel")

file_audio = {
'file': open(path_file, 'rb'),
}

header = {
'content-type': 'Audio/' + encode,
'content-length': '9999999'
}

self.command_audio(
'audio.cgi?action=postAudio&httptype={0}&channel={1}'.format(
httptype, channel),
file_content=file_audio,
http_header=header
)

def audio_stream_capture(self, httptype=None,
channel=None, path_file=None):
"""
Expand Down
18 changes: 18 additions & 0 deletions src/amcrest/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,21 @@ def command(self, cmd, retries=None, timeout_cmd=None):
except:
raise
return resp

def command_audio(self, cmd, file_content, http_header,
timeout=None):
url = self.__base_url(cmd)

if timeout is not None:
timeout = self._timeout_protocol

try:
requests.post(
url,
files=file_content,
auth=self._token,
headers=http_header,
timeout=timeout
)
except requests.exceptions.ReadTimeout:
pass

0 comments on commit 2568607

Please sign in to comment.