allure-framework / allure2

Allure Report is a flexible, lightweight multi-language test reporting tool. It provides clear graphical reports and allows everyone involved in the development process to extract the maximum of information from the everyday testing process
https://allurereport.org/
Apache License 2.0
4.07k stars 702 forks source link

Generating report with mp4 video doesn't allow video to play in served report #1358

Closed jsa34 closed 1 year ago

jsa34 commented 3 years ago

Describe the bug Upon generating a report that include a video attached to a test, the served Allure report does not allow the mp4 video to be played

To Reproduce Steps to reproduce the behavior: Attached video with the following code snippet (Python):

        with open(os.path.join(VIDEO_RECORDINGS_DIR, _video_name), "rb") as video_file:
            allure.attach(video_file.read(), name="video", attachment_type=allure.attachment_type.MP4)

Attached generated Allure results dir - mp4 video is included and plays successfully independently and the report recognises that the there is a video attached to a test, but the video cannot be played

Expected behavior Video in report plays as when playing the video independently as a separate file in a media player.

Screenshots image

Environment (please complete the following information):

| Allure version | 2.14.0 | | Test framework | pytest@6.2.4 | | Allure adaptor | allure-pytest@2.9.43 | | Generate report using | allure@2.14.0 |

Additional context Attached generated allure results dir with all artefacts: sample-allure.zip

fescobar commented 3 years ago

Did you try using a different path (something hardcoded just to check) or with different types of video or any other kind of file?

jsa34 commented 3 years ago

Interesting - I hadn't considered the video type...

MP4 doesn't work, but I swapped out the mp4 to be webm, and all is fine - only code change from Allure's side is:

        with open(os.path.join(VIDEO_RECORDINGS_DIR, _video_name), "rb") as video_file:
            allure.attach(video_file.read(), name="video", attachment_type=allure.attachment_type.WEBM)

Obviously also rendered the video with vp09 codec (webm) instead of mp4, but no other changes - mp4 and webm videos both were playing fine outside of Allure report, even the video in the results dir

fescobar commented 3 years ago

@jsa34 great!

jsa34 commented 3 years ago

Thanks, @fescobar ! Still not sure why Allure has issues with mp4 video attachments playing in the report; I will swap to webm, but leave this issue open as mp4 still doesn't work

fescobar commented 3 years ago

@jsa34 seems to be the python library doesn't have the right encodes for MP4. It could be an issue from the library.

red-sight commented 2 years ago

Same to me - generated mp4 video with latest wdio video-reporter is not playing in the allure report

AnasKhan89 commented 2 years ago

codec

@jsa34 @fescobar I am having the same problem but in my case video is still not playing with .webm and .avi. Below is my code.

File video = new File(System.getProperty("user.dir")+"/recordings/"+ (MyScreenRecorder.getLastModified(System.getProperty("user.dir")+"/recordings/").getName()));
 Allure.addAttachment("Some video", "video/avi", Files.asByteSource(video).openStream(), ".avi");


Below is my start recording code of screen recorder class (Recording the video with the help of org.monte.screenrecorder)

screenRecorder = new MyScreenRecorder(gc, captureSize,
 new Format(MediaTypeKey, MediaType.FILE, MimeTypeKey, MIME_AVI),
 new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
 CompressorNameKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, DepthKey, 24, FrameRateKey,
 Rational.valueOf(15), QualityKey, 2.0f, KeyFrameIntervalKey, 15 * 60),
 new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, "black", FrameRateKey, Rational.valueOf(30)),
 null, file, methodName);

screenRecorder.start();

When setting .avi on both screen recorder and addattachment , only the video download option is showing. When setting avi in the screen recorder and .webm in the addattachment then report recognises that there is a video attached to a test, but the video cannot be played. Can you guys please help me? I got stuck for last 2 days.

fescobar commented 2 years ago

@AnasKhan89 can you reproduce that video generated in your pc outside allure? Seems to be you are using java. Could it be? What framework are you using to attach the video?

AnasKhan89 commented 2 years ago

@fescobar Yes, I am using Java. When I am using avi format on both Screen recorder and attachment code , I am gettting the below results in report. image

There is a download link and after downloading it I am able to play it in vlc player.

allure-results-with-avi.zip

When generating video with avi format from screen recorder and use webm format in attachment code, I am getting the below results in report.

image

Report recognizes that there is a video attached to a test, but the video cannot be played.

I am running the attachment code under the @After annotation of cucumber. And yes I am able to record and run the video outside allure in pc.

fescobar commented 2 years ago

@AnasKhan89 check this example. Not sure what version are you using but it should work in the same way. https://github.com/fescobar/allure-docker-service-examples/blob/master/allure-docker-java-cucumber-jvm-example/src/test/java/com/allure/docker/steps/Hooks.java#L24

import io.qameta.allure.Allure;

 Allure.addAttachment("Some video", "video/mp4", Files.asByteSource(video).openStream(), "mp4");
vivekvasu95 commented 2 years ago

In python it is working fine.

allure.attach.file(request.session.page.video.path(), "video", allure.attachment_type.MP4)

image
qb-nikola-popovic commented 1 year ago

@jsa34 not exactly related to the issue but can I ask you to add more details on implementation?

Where did you add this block of code?

with open(os.path.join(VIDEO_RECORDINGS_DIR, _video_name), "rb") as video_file:
    allure.attach(video_file.read(), name="video", attachment_type=allure.attachment_type.WEBM)

Is it in pytest_runtest_makereport?

I'm able to take a recording and save it in .webm file, with following fixture

@pytest.fixture(autouse=True)
def record_mobile_tests(request):
    """Fixture used to record mobile tests"""

    mobile_app_dir = pathlib.Path(os.path.dirname(os.path.realpath(__file__)))
    recordings_dir = (mobile_app_dir / "recordings").resolve()

    # Create a recordings directory if one does not already exist
    if not os.path.exists(recordings_dir):
        os.makedirs(recordings_dir)

    pytest.mobile_driver.start_recording_screen(videoType='libx264')

    yield
    video_rawdata = pytest.mobile_driver.stop_recording_screen()
    test_name = request.node.name
    filepath = os.path.join(recordings_dir, f"{test_name}.webm")

    with open(filepath, "wb+") as vd:
        vd.write(base64.b64decode(video_rawdata))

But then I'm not sure how to include those recording in allure report?

Can you please help out with this a bit? Thank you in advance!

bwomsm1 commented 1 year ago

@fescobar I am also facing this problem, any solution here? I tried the WEBM coded but no success with that

bwomsm1 commented 1 year ago

Any news about this issue?

davidkastanek commented 1 year ago

Dealt with same issue. The problem is that you try to get the video when it's not ready yet. Try doing the thing below. Both closing the driver and waiting a while is important.

class TestPython(unittest.TestCase):

    def test_homepage(self):
        try:
            options=webdriver.FirefoxOptions()
            self.driver = webdriver.Remote(
                command_executor="http://localhost:4444",
                options=options
            )
            self.driver.set_window_position(0,0)
            self.driver.set_window_size(1920,1080)

            self.driver.get("http://www.python.org")
            assert "Python" in self.driver.title
        finally:
            video_path = "./videos/"+self.driver.session_id+".mp4"
            self.driver.quit()
            time.sleep(5)
            allure.attach(open(video_path, "rb").read(), name="homePageVideo", attachment_type=AttachmentType.MP4)
bwomsm1 commented 1 year ago

Dealt with same issue. The problem is that you try to get the video when it's not ready yet. Try doing the thing below. Both closing the driver and waiting a while is important.

class TestPython(unittest.TestCase):

    def test_homepage(self):
        try:
            options=webdriver.FirefoxOptions()
            self.driver = webdriver.Remote(
                command_executor="http://localhost:4444",
                options=options
            )
            self.driver.set_window_position(0,0)
            self.driver.set_window_size(1920,1080)

            self.driver.get("http://www.python.org")
            assert "Python" in self.driver.title
        finally:
            video_path = "./videos/"+self.driver.session_id+".mp4"
            self.driver.quit()
            time.sleep(5)
            allure.attach(open(video_path, "rb").read(), name="homePageVideo", attachment_type=AttachmentType.MP4)

Thanks @davidkastanek , so you are saying that the sleep in the finally scope do the work here? the video is just not ready yet?

davidkastanek commented 1 year ago

Exactly. Quitting the Webdriver is also important. I figured this out by checking the video file size in time during these operations and it kept changing, which let me to conclusion that the video file was not ready when I tried to attach it to Allure report.

davidkastanek commented 1 year ago

In other words I would close this as this is not a bug on Allure side. If you give Allure finished MP4 file, it attaches it in Python no problem.

jsa34 commented 1 year ago

Hello - just to add the bug I raised above was for an MP4 file generated that definitely was concluded - as I noted:

Attached generated Allure results dir - mp4 video is included and plays successfully independently and the report recognises that the there is a video attached to a test, but the video cannot be played

bwomsm1 commented 1 year ago

Hello - just to add the bug I raised above was for an MP4 file generated that definitely was concluded - as I noted:

Attached generated Allure results dir - mp4 video is included and plays successfully independently and the report recognises that the there is a video attached to a test, but the video cannot be played

Can you share a link to the ticket?

jsa34 commented 1 year ago

This is the ticket...? I'm the OP

zied86 commented 1 year ago

Hello Dealt with same issue. The problem is that you try to get the video when it's not ready yet. Try doing the thing below. Both closing the driver and waiting a while is important.

video_path = "./videos/"+self.driver.session_id+".mp4" self.driver.quit() time.sleep(5) allure.attach(open(video_path, "rb").read(), name="homePageVideo", attachment_type=allure.attachment_type.MP4) I have a problem on FileNotFoundError: [Errno 2] No such file or directory: './videos/3e2a65e3829a5630663f81c30765ba2d.mp4'

BlacktoBlue commented 1 year ago

Has there been any update on this issue? I am experiencing the same issue.

I use the following to record video:

def convert_pil_to_opencv(image):
    pil_image = image.convert('RGB')
    image_arrary = np.array(pil_image)
    # Convert RGB to BGR
    return image_arrary[:, :, ::-1].copy()

def make_video(context):
    # display screen resolution, get it using pyautogui itself
    SCREEN_SIZE = (GetSystemMetrics(0), GetSystemMetrics(1))
    # define the codec
    fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
    # frames per second
    fps = 30
    # create the video write object
    out = cv2.VideoWriter("output.mp4", fourcc, fps, SCREEN_SIZE)
    while context.recording:
        # make a screenshot
        img_pil = ImageGrab.grab()
        img = convert_pil_to_opencv(img_pil)
        # convert these pixels to a proper numpy array to work with OpenCV
        frame = np.array(img)
        # convert colors from BGR to RGB
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        # write the frame
        out.write(frame)
    # make sure everything is closed when exited
    cv2.destroyAllWindows()
    out.release()

def before_scenario(context, scenario):
    context.recording = True
    thread = Thread(target=make_video, args=[context])
    thread.start()
    context.videoThread = thread

def after_scenario(context, scenario):
    context.recording = False
    thread = context.videoThread
    thread.join()
    context.recording = False
    time.sleep(5)

    if scenario.status.value == 3:
        with open(f"output.mp4", "rb") as video_file:
            allure.attach(video_file.read(), name="output", attachment_type=allure.attachment_type.MP4)

This still results in the same issue as describe at the top of this bug.

EDIT: I have also tried running a scenario where the video file already exists and adding it. I get the same result.

BlacktoBlue commented 1 year ago

Has anyone had any success with attaching videos to allure reports?

davidkastanek commented 1 year ago

Has anyone had any success with attaching videos to allure reports?

Yes, do it like this:

    finally:
        if driver is not None:
            driver.quit()
        time.sleep(5)
        video_path = os.path.join(VIDEOS_DIR, driver.session_id+".mp4")
        allure.attach(open(video_path, "rb").read(), name="abc", attachment_type=AttachmentType.MP4)
        time.sleep(2)
        if os.path.exists(video_path):
            os.remove(video_path)
bwomsm1 commented 1 year ago

@baev hi, I really don't understand why you are closing the ticket? the issue is not solved yet for many users. The solution with the sleep thing is just not working.

Thanks.

Olderboy commented 3 months ago

把视频转为H.264编码有解决这个问题

zyljoker commented 1 month ago

img_v3_02db_ed1775e6-83fd-4bdf-9df5-4a41d1170eeg 我也遇到了此问题 请问怎么解决

ll-shiyi commented 3 weeks ago

Use avc1 encoding to generate a video file.

The python codes eg:

def run(self): self.running = True fourcc = cv2.VideoWriter_fourcc(*'avc1') screen_size = pyautogui.size() out = cv2.VideoWriter(self.output_file, fourcc, self.fps, screen_size) start_time = time.time() while self.running: img = pyautogui.screenshot() frame = np.array(img) frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) out.write(frame) if time.time() - start_time > self.duration: break out.release() cv2.destroyAllWindows()