I am developing a console application that alternately broadcasts videos in mp4 format, which are in a local directory. A video stream is created, broadcast to the network, using flask, or rather Response. HTTP protocol. Later, in addition to video, it was necessary to broadcast audio from a file, the .wav format.
I wanted to implement it in such a way that one route app.route('/video_feed') would broadcast video and audio in random order, conditionally in one stream.
A stream is being received in VLC.
I implemented the check in a separate function, where, depending on the type of file, that is, the extension, different functions were launched, when mp4 is for video, wav for audio.
But I ran into a problem that after the video, the audio does not start, and vice versa, after the audio, the video does not start. On the console, using simple prints, I tracked that the script sends an audio stream after the video, but at some point it just stops.
If anyone has experienced this or has thoughts on this, please let me know.
def pere():
for x in main.full_akt_table: #перебор массива с видео
path = main.path_video + x
full_name = os.path.basename(path)
name = os.path.splitext(full_name)[1]
if name == '.wav': #
with open(path, "rb") as fwav: #for audio
data = fwav.read(1024)
while data:
yield data
else:
camera = cv2.VideoCapture(path) #for video
fps = camera.get(5)
while True:
cv2.waitKey(int(600 / int(fps)))
success, frame = camera.read()
if not success:
break
else:
ret, buffer = cv2.imencode('.jpg', frame)
frame = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
#app.route('/video_feed') # роут
def video_feed():
while True: #цикл запуска, возвращает response
return Response(pere())
Related
i'm trying to save the output video.mp4 file to my dirc. it works individually, so i think my code is not wrong...
but when i use the function on app.py. the terminal is showing, it is processing. but i can't get actual video.mp4 file.
what is the problem of this?
this is original source function what i'm trying
def video():
pathIn=''
pathOut = ''
fps = 10
frame_array = []
files = [f for f in os.listdir(pathIn) if isfile(join(pathIn, f))]
#for sorting the file names properly
files.sort(key = lambda x: x[5:-4])
files.sort()
----------
for i in range(len(files)):
filename=pathIn + files[i]
#reading each files
img = cv2.imread(filename)
height, width, layers = img.shape
size = (width,height)
#inserting the frames into an image array
frame_array.append(img)
out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'avc1'), fps, size)
for i in range(len(frame_array)):
# writing to a image array
out.write(frame_array[i])
i tried individually the code and searched a lot about flask.
another function from other py is working well on flask. but only this opencv is not working.
from make_vid import video
#app.route('/upload_gpx', methods=["GET", "POST"])
def upload_gpx():
video()
return render_template('public/display_vid.html')
and my terminal shows
OpenH264 Video Codec provided by Cisco Systems, Inc.
this. so i think the video() is worked but i can't get my video.
only when i run the makevid.py, i can get my video.
i need help that how can i get the video using video() function on flask??
Hey guys I programmatically created a video using Moviepy and Gizeh. Right now it saves the final video as a mp4 file.
Is it possible to upload that video frame by frame to youtube (livestream) without saving it on my computer ?
Hi thanks for posting the question. Yes, it is possible! Since you specifically mentioned Youtube I would refer to these two references:
PYTHON FFMPEG VIDEO STREAMING DOCS
Delivering Live YouTube Content via Dash
I wish all the best. Do write if you have more questions
You can use VidGear Library's WriteGear API with its FFmpeg backend which can easily upload any live video frame by frame to YouTube (livestream) over RTMP protocol in few lines of python code as follows:
Without Audio
# import required libraries
from vidgear.gears import CamGear
from vidgear.gears import WriteGear
import cv2
# define and open video source
stream = CamGear(source="/home/foo/foo.mp4", logging=True).start()
# define required FFmpeg parameters for your writer
output_params = {
"-clones": ["-f", "lavfi", "-i", "anullsrc"],
"-vcodec": "libx264",
"-preset": "medium",
"-b:v": "4500k",
"-bufsize": "512k",
"-pix_fmt": "yuv420p",
"-f": "flv",
}
# [WARNING] Change your YouTube-Live Stream Key here:
YOUTUBE_STREAM_KEY = "xxxx-xxxx-xxxx-xxxx-xxxx"
# Define writer with defined parameters
writer = WriteGear(
output_filename="rtmp://a.rtmp.youtube.com/live2/{}".format(YOUTUBE_STREAM_KEY),
logging=True,
**output_params
)
# loop over
while True:
# read frames from stream
frame = stream.read()
# check for frame if Nonetype
if frame is None:
break
# {do something with the frame here}
# write frame to writer
writer.write(frame)
# safely close video stream
stream.stop()
# safely close writer
writer.close()
With Audio
# import required libraries
from vidgear.gears import CamGear
from vidgear.gears import WriteGear
import cv2
# define video source
VIDEO_SOURCE = "/home/foo/foo.mp4"
# Open stream
stream = CamGear(source=VIDEO_SOURCE, logging=True).start()
# define required FFmpeg optimizing parameters for your writer
# [NOTE]: Added VIDEO_SOURCE as audio-source
# [WARNING]: VIDEO_SOURCE must contain audio
output_params = {
"-i": VIDEO_SOURCE,
"-acodec": "aac",
"-ar": 44100,
"-b:a": 712000,
"-vcodec": "libx264",
"-preset": "medium",
"-b:v": "4500k",
"-bufsize": "512k",
"-pix_fmt": "yuv420p",
"-f": "flv",
}
# [WARNING]: Change your YouTube-Live Stream Key here:
YOUTUBE_STREAM_KEY = "xxxx-xxxx-xxxx-xxxx-xxxx"
# Define writer with defined parameters and
writer = WriteGear(
output_filename="rtmp://a.rtmp.youtube.com/live2/{}".format(YOUTUBE_STREAM_KEY),
logging=True,
**output_params
)
# loop over
while True:
# read frames from stream
frame = stream.read()
# check for frame if Nonetype
if frame is None:
break
# {do something with the frame here}
# write frame to writer
writer.write(frame)
# safely close video stream
stream.stop()
# safely close writer
writer.close()
Reference: https://abhitronix.github.io/vidgear/latest/help/writegear_ex/#using-writegears-compression-mode-for-youtube-live-streaming
I'm getting the error below when reading HLS(HTTP Live Streaming) segment files to OpenCV, using cv2.VideoCapture()
[mov,mp4,m4a,3gp,3g2,mj2 # 0x7f941f2ca200] could not find corresponding trex
[mov,mp4,m4a,3gp,3g2,mj2 # 0x7f941f2ca200] error reading header
The segment files are mp4 and HLS server is Amazon Kinesis Video Stream. The error message says that I'm missing header part of mp4 and it looks somehow reasonable because HLS provides a sequence of files.
My question here is, reading HLS segments to OpenCV is totally wrong approach? or we have some workaround?
import boto3
import cv2
import requests
import re
kinesis_client = boto3.client('kinesisvideo',
region_name='ap-northeast-1'
)
endpoint = kinesis_client.get_data_endpoint(
StreamARN='MY_ARN',
APIName='GET_HLS_STREAMING_SESSION_URL'
)
data_endpoint = endpoint['DataEndpoint']
url_prefix = data_endpoint + "/hls/v1/"
video_client = boto3.client('kinesis-video-archived-media',
endpoint_url=data_endpoint
)
# Retrieve HLS manifest URL from Kinesis Video Stream
session_url = video_client.get_hls_streaming_session_url(
StreamARN='MY_ARN',
HLSFragmentSelector={'FragmentSelectorType': 'PRODUCER_TIMESTAMP'}
)
session_url = session_url['HLSStreamingSessionURL']
# Fetch segment(mp4) file urls
master_playlist = requests.get(session_url)
media_playlist_url = url_prefix + master_playlist.text.split("\n")[-2]
media_playlist = requests.get(media_playlist_url)
media_playlist = media_playlist.text
pattern = r"getMP4Media"
segments = filter(lambda x: re.match(pattern,x), media_playlist.split("\n"))
for segment in segments:
segment_url = url_prefix + segment
# Debug segment url
# This emits something like: https://b-87178fb5.kinesisvideo.ap-northeast-1.amazonaws.com/hls/v1/getMP4MediaFragment.mp4?FragmentNumber=91343852333186478711651164912799448912305946338&SessionToken=CiAFReSdi9NKKz8vDum-Bs_8MFJ-5jIk06WmiyKDQQazihIQLdLPLuvr6scwc4HhAo6uDRoZWbgLHyJK01pTzFujc-cSkfl0oo4pIFD2sSIghdfInJL4XqMc_brBoLCikS73I3Nxxxxxxxxxxx
print(segment_url)
# Read mp4 file from Kinesis Video Sterams
cap = cv2.VideoCapture(segment_url)
while(cap.isOpened()):
ret, frame = cap.read()
cv2.imshow("Frame",frame)
cap.release()
I've setup my RPi, motion detector and camera to capture an image whenever motion is detected. Each time an image is captured, I'd like to automatically upload that image to Google Drive (and delete it from my RPi).
Everything seems to be working with one exception - my script captures and uploads the first image to Google Drive with no problems but then it continues to upload that same image and only that image each time the camera is subsequently triggered. The subsequent images are being captured and stored on my RPi properly, just not uploaded to Google Drive.
I'm only a couple weeks into coding so please have mercy on me (and sincere thanks for any help). Relevant bits below:
class MotionUploader:
def __init__(self, config_file_path):
config = ConfigParser.ConfigParser()
config.read(config_file_path)
def upload_snapshot(self, snapshot_file_path):
"""Upload a snapshot to the specified folder. Remove duplicates."""
folder_id = self._get_folder_id(self.snapshot_folder)
file_name = os.path.basename(snapshot_file_path)
media = MediaFileUpload(snapshot_file_path, mimetype='image/jpeg')
self.drive_service.files().insert(media_body=media, body={'title':file_name, 'parents':[{u'id': folder_id}]}).execute()
while True:
i=GPIO.input(11)
if i==0: #When output from motion sensor is LOW
print "All quiet... too quiet...",i
GPIO.output(3, 0) #Turn OFF LED
time.sleep(3)
elif i==1: #When output from motion sensor is HIGH
print "!Achtung!",i
GPIO.output(3, 1) #Turn ON LED
now = datetime.datetime.now().strftime("%m_%d_%Y_%H_%M_%S")
camera.rotation = 180
camera.start_preview()
camera.capture("/home/pi/motion-uploader/Photos/"+ now + ".jpg")
cfg_path = sys.argv[1]
vid_path = sys.argv[2]
MotionUploader(cfg_path).upload_snapshot(vid_path)
camera.stop_preview()
time.sleep(3)
I am looking for a way to save the current frame, from a specified live Twitch.tv channel, to disk. Any programming language is welcomed.
So far I've found a possible solution using Python here but unfortunately it doesn't work.
import time, Image
import cv2
from livestreamer import Livestreamer
# change to a stream that is actually online
livestreamer = Livestreamer()
plugin = livestreamer.resolve_url("http://twitch.tv/flosd")
streams = plugin.get_streams()
stream = streams['best']
# download enough data to make sure the first frame is there
fd = stream.open()
data = ''
while len(data) < 3e5:
data += fd.read()
time.sleep(0.1)
fd.close()
fname = 'stream.bin'
open(fname, 'wb').write(data)
capture = cv2.VideoCapture(fname)
imgdata = capture.read()[1]
imgdata = imgdata[...,::-1] # BGR -> RGB
img = Image.fromarray(imgdata)
img.save('frame.png')
Apparently cv2.VideoCapture(fname) returns none although it managed to write about 300K of information to stream.bin